Linux中fork()函数的详解

一:fork()的介绍

 fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程。子进程得到与父进程用户级虚拟地址空间相同的(但是独立的)一份副本,包括代码和数据段、堆、共享库以及用户栈。子进程还获得与父进程任何打开文件描述符相同的副本,当父进程调用fork时,子进程可以读写父进程中打开的任何文件。

父进程和新创建的子进程之间最大的区别在于它们有不同的PID。

fork函数只被调用一次,却会返回两次。

 

以下代码的从网上找的

Linux中fork()函数的详解

1)在父进程中,fork返回新创建子进程的进程ID;   

2)在子进程中,fork返回0;    

3)如果出现错误,fork返回一个负值

在fork函数执行完毕后,如果创建新进程成功,则出现两个进程,一个是子进程,一个是父进程。在子进程中,fork函数返回0,在父进程中,fork返回新创建子进程的进程ID。我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

每个进程都有一个独特(互不相同)的进程标识符(process ID),可以通过getpid()函数获得,还有一个记录父进程pid的变量,可以通过getppid()函数获得变量的值。

通过result=1来看,这两个进程的变量都是独立的,存在不同的地址中,不是共用的。

二.fork()的二重循环的解释

 

Linux中fork()函数的详解

 

Linux中fork()函数的详解

在父进程中,指令执行到for循环中,i=0,接着执行fork,fork执行完后,系统中出现两个进程,分别是p3906和p3907。可以看到父进程p3906的父进程是p3886,子进程p3907的父进程正好是p3906。我们用一个链表来表示这个关系:    p3886->p3906->p3907     第一次fork后,p3906(父进程)的变量为i=0,fpid=3907(fork函数在父进程中返向子进程id)

第一次fork后,p3906(父进程)的变量为i=0,fpid=3907(fork函数在父进程中返向子进程id)

p3907(子进程)的变量为i=0,fpid=0(fork函数在子进程中返回0)

父进程p3906先执行,当进入下一个循环时,i=1,接着执行fork,系统中又新增一个进程p3908,对于此时的父进程,p3886->p3906(当前进程)->p3908(被创建的子进程)。

  对于子进程p3907,执行完第一次循环后,i=1,接着执行fork,系统中新增一个进程p3909,对于此进程,p1566->p3907(当前进程)->p3909(被创建的子进程)。从输出可以看到p3907原来是p1566的子进程,现在变成p3909的父进程。父子是相对的。只要当前进程执行了fork,该进程就变成了父进程了,就打印出了parent。

创建了两个进程p3908,p3909,这两个进程执行完printf函数后就结束了,因为这两个进程无法进入第三次循环,无法fork,该执行return 0;了,其他进程也是如此。  细心的读者可能注意到p3908,p3909的父进程难道不该是p3906和p3907吗,怎么会是1呢?这里得讲到进程的创建和死亡的过程,在p3906和p3907执行完第二个循环后,main函数就该退出了,也即进程该死亡了,因为它已经做完所有事情了。p3906和p3907死亡后,p3908,p3909就没有父进程了,这在操作系统是不被允许的,所以p3908,p3909的父进程就被置为p1了,p1是永远不会死亡的。

每次程序运行的结果会稍有不同,这是因为进程执行没有固定的先后顺序,哪个进程先执行要看系统的进程调度策略。

三.fork的三重循环

Linux中fork()函数的详解

 for        i=0         1           2

             father     father     father

                                       son

                           son       father

                                       son

              son       father     father

                                       son

                           son       father

                                       son    其中每一行分别代表一个进程的运行打印结果。