从一道面试题谈linux下fork的运行机制

来源:互联网 发布:java 从文件读入二进制 编辑:程序博客网 时间:2024/05/16 06:56

转自:http://hi.baidu.com/yuesoq520/blog/item/96fba8eb0632a234b90e2d48.html

今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目:

      给出如下C程序,在linux下使用gcc编译:

1 #include "stdio.h"
2 #include "sys/types.h"
3 #include "unistd.h"
4
5 int main()
6 {
7 pid_t pid1;
8 pid_t pid2;
9
10 pid1 = fork();
11 pid2 = fork();
12
13 printf("pid1:%d, pid2:%d\n", pid1, pid2);
14 }

      要求如下:

      已知从这个程序执行到这个程序的所有进程结束这个时间段内,没有其它新进程执行。

      1、请说出执行这个程序后,将一共运行几个进程。

      2、如果其中一个进程的输出结果是“pid1:1001, pid2:1002”,写出其他进程的输出结果(不考虑进程执行顺序)。

      明显这道题的目的是考察linux下fork的执行机制。下面我们通过分析这个题目,谈谈linux下fork的运行机制。

预备知识

      这里先列出一些必要的预备知识,对linux下进程机制比较熟悉的朋友可以略过。

      1、进程可以看做程序的一次执行过程。在linux下,每个进程有唯一的PID标识进程。PID是一个从1到32768的正整数,其中1一般是特殊进程init,其它进程从2开始依次编号。当用完32768后,从2重新开始。

      2、linux中有一个叫进程表的结构用来存储当前正在运行的进程。可以使用“ps aux”命令查看所有正在运行的进程。

      3、进程在linux中呈树状结构,init为根节点,其它进程均有子进程,某进程的父进程就是启动这个进程的进程,这个进程叫做父进程的子进程。

      4、fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程。

解题的关键

      有了上面的预备知识,我们再来看看解题的关键。我认为,解题的关键就是要认识到fork将程序切成两段。看下图:

      上图表示一个含有fork的程序,而fork语句可以看成将程序切为A、B两个部分。然后整个程序会如下运行:

      step1、设由shell直接执行程序,生成了进程P。P执行完Part. A的所有代码。

      step2、当执行到pid = fork();时,P启动一个进程Q,Q是P的子进程,和P是同一个程序的进程。Q继承P的所有变量、环境变量、程序计数器的当前值。

      step3、在P进程中,fork()将Q的PID返回给变量pid,并继续执行Part. B的代码。

      step4、在进程Q中,将0赋给pid,并继续执行Part. B的代码。

      这里有三个点非常关键:

      1、P执行了所有程序,而Q只执行了Part. B,即fork()后面的程序。(这是因为Q继承了P的PC-程序计数器)

      2、Q继承了fork()语句执行时当前的环境,而不是程序的初始环境。

      3、P中fork()语句启动子进程Q,并将Q的PID返回,而Q中的fork()语句不启动新进程,仅将0返回。

解题

      下面利用上文阐述的知识进行解题。这里我把两个问题放在一起进行分析。

      1、从shell中执行此程序,启动了一个进程,我们设这个进程为P0,设其PID为XXX(解题过程不需知道其PID)。

      2、当执行到pid1 = fork();时,P0启动一个子进程P1,由题目知P1的PID为1001。我们暂且不管P1。

      3、P0中的fork返回1001给pid1,继续执行到pid2 = fork();,此时启动另一个新进程,设为P2,由题目知P2的PID为1002。同样暂且不管P2。

      4、P0中的第二个fork返回1002给pid2,继续执行完后续程序,结束。所以,P0的结果为“pid1:1001, pid2:1002”。

      5、再看P2,P2生成时,P0中pid1=1001,所以P2中pid1继承P0的1001,而作为子进程pid2=0。P2从第二个fork后开始执行,结束后输出“pid1:1001, pid2:0”。

      6、接着看P1,P1中第一条fork返回0给pid1,然后接着执行后面的语句。而后面接着的语句是pid2 = fork();执行到这里,P1又产生了一个新进程,设为P3。先不管P3。

      7、P1中第二条fork将P3的PID返回给pid2,由预备知识知P3的PID为1003,所以P1的pid2=1003。P1继续执行后续程序,结束,输出“pid1:0, pid2:1003”。

      8、P3作为P1的子进程,继承P1中pid1=0,并且第二条fork将0返回给pid2,所以P3最后输出“pid1:0, pid2:0”。

      9、至此,整个执行过程完毕。

      所得答案:

      1、一共执行了四个进程。(P0, P1, P2, P3)

       2、另外几个进程的输出分别为:

       pid1:1001, pid2:0

      pid1:0, pid2:1003

      pid1:0, pid2:0

      进一步可以给出一个以P0为根的进程树:

验证

      下面我们去linux下实际执行这个程序,来验证我们的答案。

      程序如下图:

      用gcc编译、执行后结果如下:

      由于我们不太可能刚巧碰上PID分配到1001的情况,所以具体数值可能和答案有所差别。不过将这里的2710看做基数的话,结果和我们上面的解答是一致的。

总结

      应该说这不是一道特别难或特别刁钻的题目,但是由于fork函数运行机制的复杂性,造就了当两个fork并排时,问题就变得很复杂。解这个题的关键,一是 要对linux下进程的机制有一定认识,二是抓住上文提到的几个关于fork的关键点。朋友说,这个题给的时间是5分钟,应该说时间还算充裕,但是在面试 的场合下,还是很考验一个人对进程、fork的掌握程度和现场推理能力。

      希望本文能帮助朋友们对fork的执行机制有一个明晰的认识。

-----------------------------------------------------------------------------------------------------------------------------------

补充:

fork

  fork()函数,Linux系统调用
  头文件:
  #include <unistd.h>
  函数定义:
  int fork( void );
  返回值:
  子进程中返回0,父进程中返回子进程ID,出错返回-1
  函数说明:
  一个现有进程可以调用fork函数创建一个新进程。由fork创建的新进程被称为子进程(child process)。fork函数被调用一次但返回两次。两次返回的唯一区别是子进程中返回0值而父进程中返回子进程ID。

全局变量fork后是共享还是复制一份呢?答案是复制一份。

做如下实验:

#include <unistd.h>
#include <stdio.h>
int g_int;

int main(int argc,void** argv)
{
int pid;

pid = fork();
if(pid != 0)
{
   g_int =5;
   sleep(2);
        printf("parent:g_int = %d\n",g_int);
}else{
   g_int = 6;
   printf("child:g_int = %d\n",g_int);
}
}
结果是:

child:g_int = 6;
parent:g_int=5;

如果是共享的话,g_int 应该也是6才对。

父进程中的指针指向的内容(也就是堆数据)会被复制吗?待验证。

父进程已经打开的文件对象会被复制吗?不会

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 8岁骨龄11岁怎么办啊 13岁初中生有思想不听话怎么办 交朋友找对象喜欢颜值高的怎么办 儿子找对象不听父母怎么办 缺爱怎么办的搞笑回答 对象说有人追她怎么办 说了一句话媳妇非常生气怎么办 柔顺后头发太臭怎么办 积分兑换手机被骗了怎么办 老板对你的上级不满怎么办 如果老板不给工资怎么办 手机号码被标记为其他公司怎么办? 被标记为骚扰电话怎么办 手机被标记骚扰电话怎么办 360摄像头不支持5g怎么办 摄像头不支持5g网络怎么办 家里的wifi卡了怎么办 办信用卡没有座机号码怎么办 拨打电话时显示号码有误怎么办 个体营业执照怎么办企业支付宝 没满16岁怎么办电话卡 我的电话卡丢了怎么办 公司注销地税没有补齐怎么办 公司没有固定电话怎么办信用卡 申请信用卡公司没有固定电话怎么办 办理信用卡公司没有固定电话怎么办 江门市固话欠费停机后怎么办 物业交钥匙地面有裂缝怎么办 深圳交通卡丢了怎么办 没装etc走etc怎么办 找不到过敏源身体痒怎么办 微信客服电话打不通怎么办 华为手机网络信号不好怎么办 酷我好友动态加载不了怎么办? 米兔电话手表停机了怎么办 糖猫电话手表停机了怎么办 360电话手表停机了怎么办 小天才电话手表停机怎么办 移动手机卡不知道号码怎么办 天猫退款手机号换了怎么办 科目二考试脚抖怎么办