`
xcxinghai
  • 浏览: 32218 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

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

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

今天一位朋友去一个不错的外企面试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:%d\n", 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的执行机制有一个明晰的认识。


转自:http://kb.cnblogs.com/page/76622/


我自己的理解:



从图中可以看出,主线程fork出的线程,fork的返回值就是该线程的pid,但是对于主线程fork的返回值却是0。从图中一目了然的就可以知道另外的3中情况。


ps:我的新博客地址:http://www.xinghaixu.com

分享到:
评论

相关推荐

    linux面试题看FORK()

    linux面试题看FORK()

    linux下fork的运行机制参考.pdf

    linux下fork的运行机制 fork是Linux中一个非常重要的系统调用,它允许一个进程创建一个新的进程,该新进程是当前进程的副本。 fork的运行机制是Linux中进程创建的基础。 在Linux中,每个进程都有唯一的PID标识进程...

    linux_fork函数

    linux_fork函数

    linux c fork全面剖析

    linux c fork全面剖析 linux c fork全面剖析 linux c fork全面剖析 linux c fork全面剖析 linux c fork全面剖析

    Linux下Fork与Exec使用

    与DOS和早期的Windows不同,Unix/Linux系统是真正实现多任务操作的系统,可以说,不使用多进程编程,就不能算是真正的Linux环境下编程。  多线程程序设计的概念早在六十年代就被提出,但直到八十年代中期,Unix...

    linux 进程 线程 fork 的深入思考

    linux 进程 线程 fork 的深入思考 一道面试题的思考

    linux下fork函数实例

    用fork创建子进程; 回答no执行父进程,yes执行父进程并复制进程的操作;在父进程将str3,str4接至str0中,并输出str0 ;在子进程中,将str1,str2接至str0中,并输出str0

    linux下fork系统调用分析

    linux下fork系统调用分析。设计do_fork,copy_process函数以及x86体系下系统调用执行过程。更多分析请看edsionte.com.linux下fork系统调用分析。设计do_fork,copy_process函数以及x86体系下系统调用执行过程。更多...

    linux下socket和fork结合使用的例子

    linux下socket和fork结合使用的例子,描述了socket的基本流程和如何采用子进程处理客户端请求

    常见linux 嵌入式开发C语言笔试面试题

    "常见Linux嵌入式开发C语言笔试面试题" 本文总结了Linux嵌入式开发C语言笔试面试题中的重要知识点,包括进程和线程的基本概念、多进程和多线程的优缺点、进程和线程的状态转换、父进程和子进程的关系、进程通信的...

    linux fork函数

    一些简单的linux下进程管理文件示例,关于fork()函数的,可以作为入门级别的

    fork process on linux

    使用linux来fork程序 "Fork",除了它是一個當你不停地敲入后看起來非常奇怪的單詞以外,通常是指 Unix 產生新進程的方式。由于系統調用的用法將會在其他 IPC 的文檔中出現,本文只是一個快速的,不太精确的 fork() ...

    在win系统下模拟linux中的fork()函数执行过程与基础通信过程

    在win系统下模拟linux中的fork()函数执行过程与基础通信过程 备注清晰。

    Linux环境下的Fork使用

    这是我个人总结的关于多线程的一点心得体会,希望对大家有一定的帮助

    前端大厂最新面试题-fork_clone_branch.docx

    前端大厂最新面试题-fork_clone_branch.docx

    linux 多进程编程 fork

    linux 多进程编程 forklinux 多进程编程 forklinux 多进程编程 forklinux 多进程编程 forklinux 多进程编程 forklinux 多进程编程 forklinux 多进程编程 forklinux 多进程编程 forklinux 多进程编程 forklinux 多...

    linux驱动面试题.pdf

    本文将从 Linux 驱动面试题中提炼出重要的知识点,涵盖 GPIO、触摸屏原理、Linux 命令执行、内存管理、宏定义、Socket 编程等方面。 1. GPIO(General Purpose Input/Output) GPIO 是一种相对于芯片本身而言的...

Global site tag (gtag.js) - Google Analytics