一家不错的外企面试linux开发岗位。面试官问了下面的问题:给定如下C程序,在Linux下使用gcc编译:从这个程序可知,从执行到这个程序的所有进程结束的这段时间里,没有其他新的进程被执行.请告诉我执行此程序后将运行多少个进程。如果其中一个进程的输出是“pid1:1001,pid2:1002”,写入其他进程的输出(不管进程执行的顺序如何)。很明显这道题的目的是考察linux下fork的执行机制。下面我们就分析一下这个话题,说说Linux下fork的运行机制。预备知识:这里罗列了一些必要的预备知识,熟悉Linux下进程机制的朋友可以略过。一个进程可以看成是一个程序的执行过程。在Linux下,每个进程都有一个唯一的PID来标识进程。PID是1到32768的正整数,其中1一般是特殊进程init,其他进程从2开始依次编号。当你用完32768时,从2重新开始。Linux中有一个叫做进程表的结构来存储当前运行的进程。您可以使用“psaux”命令查看所有正在运行的进程。进程在Linux中是树状结构,init是根节点,其他进程都有一个父进程。进程的父进程是启动进程的进程。这个进程称为父进程的子进程。fork的作用是复制一个与当前进程相同的进程。新进程的所有数据(变量、环境变量、程序计数器等)值与原进程一致,但它是一个全新的进程,它作为原进程的子进程。解题关键:有了上面的初步知识,我们再来看看解题的关键。在我看来,解决问题的关键是意识到fork将程序一分为二。看下图:上图是一个包含fork的程序,fork语句可以看做是把程序分成了A和B两部分,那么整个程序会运行如下:step1.假设程序直接被shell执行,生成一个进程P。P执行Part的所有代码。A.step2,当执行到pid=fork();时,P启动了一个进程Q,Q是P的子进程,与P是同一个程序的进程。Q继承了P的所有变量,环境变量,和程序计数器的当前值。第三步。在P进程中,fork()将Q的PID返回给变量pid,继续执行Part的代码。B.步骤4。在进程Q中,将pid赋值为0,继续执行Part的代码。B、这里有3个关键点:P执行所有程序,而Q只执行Part。B,就是fork()之后的程序。(这是因为Q继承了P的PC程序计数器)Q继承的是执行fork()语句时的当前环境,而不是程序的初始环境。P中的fork()语句启动子进程Q,返回Q的PID,而Q中的fork()语句不启动新进程,只返回0。解决这个问题。这里我把两个问题放在一起分析。从shell执行这个程序并启动一个进程。我们把这个进程设为P0,把它的PID设为XXX(求解问题的进程不需要知道它的PID)。当pid1=fork();执行后,P0启动了一个子进程P1,根据标题P1的PID为1001。让我们暂时忽略P1。P0中的fork返回1001给pid1,继续执行直到pid2=fork();,此时又启动了一个新的进程,设为P2,P2的PID如题所示为1002。现在也忽略P2。P0中的第二次fork返回1002给pid2,继续执行后续程序,结束。所以,P0的结果是“pid1:1001,pid2:1002”。再看P2。生成P2时,P0中的pid1=1001,所以P2中的pid1继承了P0的1001,作为子进程的pid2=0。p2在第二次fork后开始执行,结束后输出“pid1:1001,pid2:0”。再看P1,P1中第一个fork返回0给pid1,然后执行下面的语句。而下面的语句就是pid2=fork();执行到这里,P1生成一个新的进程,设置为P3。不管P3。P1中的第二个fork将P3的PID返回给pid2。根据初步了解,P3的PID为1003,所以P1的pid2=1003。P1继续执行后续程序,结束,输出“pid1:0,pid2:1003”。P3作为P1的子进程,从P1继承了pid1=0,第二次fork返回0给pid2,所以P3***输出“pid1:0,pid2:0”。至此,整个执行过程就完成了。得到的答案:1、一共执行了四个进程。(P0,P1,P2,P3)2.其他几个进程的输出是:pid1:1001,pid2:0pid1:0,pid2:1003pid1:0,pid2:0可以进一步给出一个以P0为根的进程Tree:验证:让我们去在linux下实际执行这个程序来验证我们的答案。程序如下图所示:用gcc编译执行后,结果如下:由于我们不太可能碰巧把PID赋值给1001,所以具体值可能和答案不一样。但是,如果把这里的2710作为基数,结果和我们上面的答案是一致的。小结:应该说这不是一个特别难或者特别棘手的问题,但是由于fork函数运行机制的复杂性,当两个fork并排的时候,问题就变得很复杂了。解决这个问题的关键一是对linux下进程的机制有一定的了解,二是要抓住上面提到的关于fork的要点。朋友说这道题给的时间是5分钟。应该说时间是充裕的,但是在面试的情况下,还是很考验一个人对流程、叉子的掌握程度,以及现场推理能力的。
