注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

Fork的详解  

2014-06-24 18:56:04|  分类: LINUX编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Fork的详解

在类UNIXLINUX编程中,多进程的编程是不可避免,甚至在一些场合还要使用进程池。早先在LINUX上是没有线程的,所以多进程编程是必须掌握的知识。

使用fork创建进程,细节有很多,一个把握不清楚,就会产生意想不到结果。让你感觉到在LINUX下编程确实是不如在WIN上编程的轻松。但是越是如此,越要把它搞好。

还是老规矩,看代码:

#include <unistd.h>

#include <stdio.h>

 

int main()

{

int i = 0;

for (i = 0;i < 3;i++)

{

         pid_t fpid = fork();

if (fpid ==0)

{

         printf("son\n");

//return 0;

}

else

{

         printf("father\n");

}

}

 

return 0;

}

那么上面的代码会产生多少子进程呢?看结果,不要轻易下结论:

/epolltest$ ./main

father

father

son

father

father

son

father

father

son

father

son

son

son

son

根据网上的资料其会产生1+2+…2(N-1次方)个子进程,同时会打印2*1+2…2(N-1次方))个结果(fork会产生两次返回结果)。如果算上自己也就是父进程的话是2(N次方)。那这个数据是怎么来的呢?

先简要的介绍一下fork()系统调用,在linux,fork()调用会调用clone(),clone()最终会调用 do_fork()系统调用来产生子进程,关键是这个子进程怎么产生的。在linux/unix中,fork()产生的子进程相当于复制了整个父进程,首先复制了PCB,然后将内存页表共享到父进程的页面(写时复制)。通俗一点,子进程和父进程看起来是完全一样的,一样的代码段,一样的数据段,一样的进程控制块,但是他们是独立的,并且从内核返回到用户态时,系统调用对原进程返回子进程的pid,对子进程返回0,这样就可以区分父子进程了。

回到上面的问题,为什么答案3是错的,举个例子:父进程i=0的时候fork()了一个子进程p1,但是p1现在和父进程的状态是一样的,也就是会继续接着循环,从i=1fork()一个p2,p2又会继续从i=3开始来fork()其他的子进程,这样就会产生很多很多子进程了。

现在来求解具体的产生的进程的个数。

f(n)表示程序中循环会执行n次时整个程序会产生的进程数,很容易得到递推公式:

f(n)=1+f(n-1)+f(n-2)+f(n-3)+…+f(0)

比如for i=0;i

因为i=0fork()的子进程下次会继续循环n-1次,i=1 fork()的子进程下次会仅需循环n-2 次。。。。

其中常数1是进程本身。

边界条件,f(0)=1

这样,我们就得到了问题的答案:

f(n)=1+f(n-1)+f(n-2)+…+f(0)

f(0)=1

这个可以求出闭形式:

f(0)=1

f(1)=2

f(2)=4

用数学归纳法可以得到f(n)=2^n

所以对于程序一,会打印出2^3-1=31行信息。

对于程序二,总共会产生2^3=32个进程。

那么这又会产生一个问题,如果使用线程池如果这么算,那么啥时候儿是个头儿啊,如果想产生几十个进程还不得头大,不慌,有办法而且很简单

把代码中的注释去掉就可以了,也就是说,在子进程里直接退出,不再让他循环就OK了。

一个个坑儿,太坑人。

 

  评论这张
 
阅读(427)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017