fork()调用的一个趣题--fork函数能生成几个子进程???
2011-07-20 11:09
579 查看
原文载于:http://202.117.3.13/wordpress/?p=81经常看到有人问到这样一个问题:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> int main() { int pid=0; for(int i=0;i<5;i++) { pid=fork(); if(pid==0) { printf("pid:%d\n",getpid()); } } return 0; }问最后打印了多少行pid:xxx.很多人一看,认为很简单,不就产生了5个子进程嘛,答案就是5个,这样回答可以说压根没有理解Linux/Unix中 fork()系统调用是怎么实现的。上面的问题等价于问这个程序总共产生了多少个进程(算自身)an,最后的答案就是an-1,因为最开始的进程不会打印这条信息,如果把程序这样改一下:
#include <stdio.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main() { int pid=0; for(int i=0;i<5;i++) { pid=fork(); wait(NULL); } printf("pid:%d\n",getpid()); return 0; }那么答案很明显就是所有的进程个数an,上面加入wait调用的目的是使各个进程不交叉输出信息。为了求an,先简要的介绍一下fork()系统调用,在linux中,fork()调用会调用clone(),而clone()最终会调用 do_fork()系统调用来产生子进程,关键是这个子进程怎么产生的。在linux/unix中,fork()产生的子进程相当于复制了整个父进程,首先复制了PCB,然后将内存页表共享到父进程的页面(写时复制)。通俗一点,子进程和父进程看起来是完全一样的,一样的代码段,一样的数据段,一样的进程控制块,但是他们是独立的,并且从内核返回到用户态时,系统调用对原进程返回子进程的pid,对子进程返回0,这样就可以区分父子进程了。回到上面的问题,为什么答案5是错的,举个例子:父进程i=0的时候fork()了一个子进程p1,但是p1现在和父进程的状态是一样的,也就是会继续接着循环,从i=1来fork()一个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=0时fork()的子进程下次会继续循环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)=1f(1)=2f(2)=4…用数学归纳法可以得到f(n)=2^n所以对于程序一,会打印出2^5-1=31行信息。对于程序二,总共会产生2^5=32个进程。
相关文章推荐
- fork()调用的一个趣题--fork函数能生成几个子进程???
- 使用python的os.fork()为一个主进程生成多个子进程
- linux下调用fork()生成进程的一些细节
- Linux 调用fork()创建两个子进程
- [Linux进程]使用fork函数创建多个子进程
- 实验 9-1 1. 实现以下功能 a) 调用 pipe()创建无名管道 b) 调用 fork 创建一个子进程 c) 在子进程中向管道内写入 128k 数据,打印出进程号及成功写入的字节数 d) 在父
- eclipse 中main()函数中的String[] args如何使用?通过String[] args验证账号密码的登录类?静态的主方法怎样才能调用非static的方法——通过生成对象?在类中制作一个方法——能够修改对象的属性值?
- ★实验 9-2 1. 补全代码,实现以下功能 a) 调用pipe()创建无名管道 b) 调用fork创建一个子进程 c) 在父进程中向管道写入 “helloworld”, 同时打印出PID和写入
- 用fork函数,由一个父进程生成两个子进程
- 进程系统调用——fork函数深入理解
- fork函数创建一个新进程
- 一个进程 fork 多个子进程
- fork()调用的一个趣题
- 关于fork函数生成父子进程变量虚拟地址
- 调用fork并使子进程建立一个新的会话
- 一个进程 fork 多个子进程
- 用fork()函数生成进程链、进程扇和进程二叉树
- 如何在一个进程中生成两个子进程?
- 简单分析Python中用fork()函数生成的子进程
- linux下通过调用fork函数实现多进程