1、fork()创建子进程详细步骤
2、fork()系统调用函数用法
一个现有进程可以调用fork函数创建一个新的进程。
#include《unistd.h>
pid_t fork(void);
返回值:子进程中返回0,父进程中返回子进程的ID,出错返回-1
fork函数被调用一次,但返回两次。两次返回的唯一出别是child process的返回值是0,而父进程的返回值则是child process的进程ID。所以可以通过fork函数的返回值来进入父子进程独有的代码段(但是要借助ifelse(else if else )选择语句)。
注:父子进程共享代码段,但是分别拥有自己的数据段和堆栈段
注:这里的父进程就是执行的main函数。子进程是父进程的副本,开始于fork函数
从fork函数开始以后的代码父子共享,即父进程要执行这段代码,子进程也要执行这段代码。(子进程获得父进程数据空间,堆和栈的副本。但是父子进程并不共享这些存储空间部分。父,子进程共享代码段。)现在很多现实并不执行一个父进程数据段,栈和堆的完全复制。而是采用写时复制技术。这些区域有父子进程共享,而且内核将他们的访问权限改变为只读的。如果父子进程中的任一个试图修改这些区域,则内核只为修改区域的那块内存制作一个副本,通常是虚拟存储器系统中的一“页”。
显然这样有助于节约内存。
一般来说,在fork之后的父进程先执行还是子进程先执行是不确定的。(取决于内核的调度算法)
因为fork使子进程得到的返回值是0,子进程可以通过这个返回值来确定自己执行代码(若有),通过if else 语句来确定实现。而这个ID=0的进程不可能是其他的进程,因为进程ID=0总是由内核交换进程使用,返回值pid<0,即是pid=-1,fork函数创建进程失败。而pid大于即子进程的ID返回给父进程(每个进程都有一个非负整数表示的唯一进程ID)。所以通过这个子进程ID,父进程也可以确定自己独有的可执行代码(若有)。其他fork之后的代码父子进程都要执行,除非有进程退出,或者通过pid的选择语句。
执行后的结果。可以看出共享代码段,独有自己数据段和堆栈段(写时复制技术)。
子进程可以通过getppid函数获得自己父进程的ID,进程可以通过getpid函数获得自己的ID。
2、一个fork() puzzle
Consider the below code snippet:
int main() { fork(); fork(); fork(); printf("Hello World\n"); }
The output:[on ubuntu 12.04]
aashish@aashish-laptop:~$ ./a.out Hello World Hello World Hello World aashish@aashish-laptop:~$ Hello World <--------------------------- Hello World Hello World Hello World Hello World
|
The short answer is that you are creating multiple processes, which run asynchronously with respect to each other. The long answer follows: When you type ./a.out at the shell prompt, that creates a process running your program. Let's call that process 1. Process 1 calls fork(). This creates a new child process, Process 2, and both 1 and 2 carry on execution after the first fork() call, proceeding to the second fork() call. Process 1 creates child Process 3, and Process 2 creates child process 4. All four processes carry on from after the second fork(), proceeding to the final fork() call. Process 1 creates Process 5; Process 2 creates Process 6; Process 3 creates Process 7; and Process 4 creates Process 8. Note that these process numbers are arbitrary: there's no guarantee they'd be created in that order. The asynchrony comes into play as soon as that first fork() gets executed. The system offers no guarantees about scheduling the parent with respect to the child. Theoretically the child could run to completion before the parent continues, the parent could finish before the child gets any resources. The most likely scenario lies somewhere in the middle: the original process shares resources with its progeny, so that all run concurrently. The final piece of the puzzle results from the fact that the shell is waiting for Process 1 to complete.Only Process 1. The shell doesn't know (or care) that Process 1 has started other processes. So when Process 1 completes, the shell displays a prompt. As it happened, some of the descendants of Process 1 hadn't yet reached the printf() statement. By the time they got there, the shell had already displayed its prompt. To explore this further, you might want to try changing the fork() calls toprintf( "%d\n", fork() ); and/or changeprintf("Hello World\n") toprintf("Hello from pid %d\n", getpid() ) |
参考 http://qing.blog.sina.com.cn/2161971512/80dd1138330012j6.html
http://*.com/questions/11802055/fork-outputs-after-the-process-execution-is-over