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

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

#include "stdio.h"

#include "sys/types.h"

#include "unistd.h"

int main()

{

pid_t pid1;

pid_t pid2;

pid1 = fork();

pid2 = fork();

printf("pid1:%d, pid2:%dn", pid1, pid2);

}

要求如下:

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

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的执行机制有一个明晰的认识。

更多干货资料点击这里

机制 linux_从一道面试题谈linux下fork的运行机制相关推荐

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

    http://kb.cnblogs.com/page/76622/ 今天一位朋友去一个不错的外企面试linux开发职位,面试官出了一个如下的题目: 给出如下C程序,在linux下使用gcc编译: #i ...

  2. LINUX下FORK的运行机制详细解析

    摘要:由于fork函数运行机制的复杂性,造就了当两个fork并排时,问题就变得很复杂.解这个题的关键,一是要对linux下进程的机制有一定认识,二是抓住上文提到的几个关于fork的关键点. 今天一位朋 ...

  3. vss2010c语言怎么运行,在Linux下使用gcc运行C语言程序

    Linux下使用最广泛的C/C++编译器是GCC,大多数的Linux发行版本都默认安装,不管是开发人员还是初学者,一般都将GCC作为Linux下首选的编译工具.本教程毫不犹豫地使用GCC来编译C程序. ...

  4. 【linux】linux中fork()详解(实例讲解)|fork的运行机制

    目录 linux中fork()函数详解 从一道面试题谈linux下fork的运行机制 linux中fork()函数详解 原文:linux中fork()函数详解(原创!!实例讲解)_jason314的博 ...

  5. 从一道面试题谈起,大厂到底看重程序员的什么能力?

    唐磊,他谦逊的自我介绍,是"在阿里云打工的清华学渣". 上周的一篇<字符串比较,居然暗藏玄机>,我最早是在唐磊<这10行比较字符串相等的代码给我整懵了>里看 ...

  6. 从一道笔试题谈算法优化(下)

    因为受到经济危机的影响,我在 bokee.com 的博客可能随时出现无法访问的情况:因此将2005年到2006年间在 bokee.com 撰写的博客文章全部迁移到 csdn 博客中来,本文正是其中一篇 ...

  7. 从一道笔试题谈算法优化(上)

    因为受到经济危机的影响,我在 bokee.com 的博客可能随时出现无法访问的情况:因此将2005年到2006年间在 bokee.com 撰写的博客文章全部迁移到 csdn 博客中来,本文正是其中一篇 ...

  8. Linux下程序的保护机制(checksec)

    Linux下程序的保护机制 前言 相信很多人,查看程序信息时会用到,checksec这个命令.它会给你返回如下图的结果,但是很多最开始看到的人,很多都看不懂,如果身为小白的我,跟在大佬后面比葫芦画瓢, ...

  9. shell for循环1到100_浅谈Linux下shell 编程的for循环常用的6种结构

    浅谈Linux下shell 编程的for循环常用的6种结构 1. 常用for循环结构 (1) for 变量 in 值1 值2 值3... do 程序块儿 done (2) for 变量 in `命令` ...

最新文章

  1. JDK源码研究Jstack,JMap,threaddump,dumpheap的原理
  2. 希捷期望HAMR实现其营收的增长
  3. ​浅谈Asp.net的sessionState
  4. 使用Qt创建XML文档及XML文档的增删改
  5. .NET分布式事务处理
  6. c语言字符型计算器,求用c语言编程四则混合运算计算器?
  7. 学前端有什么好方法,怎么才能更快学会前端?
  8. Go 编程怎么也有踩内存?
  9. 如何在JavaScript中获取字符串数组的字符串?
  10. PyTorch学习—6.PyTorch数据读取机制Dataloader与Dataset
  11. 目标追踪论文之狼吞虎咽(1):VITAL算法
  12. Android APP原型设计,五款移动APP在线原型设计工具,值得收藏
  13. crmeb知识付费二开文档
  14. 如何把pdf拆分成一页一页的图片?
  15. [MvcCore]记录部署好的应用程序突然无法访问的一次蹩脚经历!
  16. [网易]2018校园招聘编程题真题集合
  17. 【每日蓝桥】10、一三年省赛Java组真题“剪格子”
  18. k m kb mb计算机组成,为什么对计算机存储单位(K,M,G,T)换算,总是糊里又糊涂?
  19. AndroidCamera学习笔记一 硬件
  20. 中国污水源热泵运行现状分析与投资策略报告2022-2027年

热门文章

  1. 【渝粤教育】 国家开放大学2020年春季 2772家畜环境卫生与设施 参考试题
  2. 【渝粤题库】陕西师范大学189101 消费者行为学Ⅰ 作业(高起专)
  3. 【渝粤题库】国家开放大学2021春1356高级英语听说(2)题目
  4. Java注解参数类型枚举值_EffectiveJava-5-枚举和注解
  5. ecshop 模板 php代码,ecshop无法在模板文件.dwt和.lbi中直接添加php代码的解决方法...
  6. yum配置文件 重启后还原_江湖救急 : CentOS7.5 /usr 目录误删, 恢复操作.
  7. 一个小例子体会Java反射的动态性
  8. 深入浅出组合逻辑电路(3)常见的几种编码器
  9. canvas绘制多边形
  10. Property Animator 属性动画概述与示例