Talking about the operating mechanism of fork under Linux from an interview question

640?wxfrom=5&wx_lazy=1


640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1


A good foreign company interviewed for a Linux development position. The interviewer asked the following question:


640?wx_fmt=png&wxfrom=5&wx_lazy=1

Given the following C program, compiled with gcc under linux:


It is known that during the time period from the execution of this program to the end of all processes of this program, no other new process is executed.


1. Please say that after executing this program, there will be a total of several processes running.


2. If the output of one of the processes is "pid1:1001, pid2:1002", write the output of the other processes (regardless of the execution order of the processes).


Obviously the purpose of this question is to examine the execution mechanism of fork under linux. Let's talk about the operating mechanism of fork under Linux by analyzing this topic.


Prerequisites:


Here are some necessary preliminaries listed first, friends who are familiar with the process mechanism under Linux can skip it.


1. A process can be regarded as an execution process of a program. Under Linux, each process has a unique PID to identify the process. PID is a positive integer from 1 to 32768, where 1 is generally a special process init, and other processes are numbered sequentially from 2. When you run out of 32768, start over from 2.


2. There is a structure called process table in Linux to store the currently running process. All running processes can be viewed with the "ps aux" command.


3. The process is in a tree structure in Linux, init is the root node, and other processes have parent processes. The parent process of a process is the process that starts the process. This process is called the child process of the parent process.


4. The role of fork is to copy a process that is the same as the current process. The values ​​of all data (variables, environment variables, program counters, etc.) of the new process are the same as those of the original process, but it is a brand new process and is used as a child process of the original process.


The key to solving the problem:


With the above preparatory knowledge, let's take a look at the key to solving the problem. The key to solving the problem, I think, is to realize that fork cuts a program into two pieces. Look at the picture below:


640?


The figure above shows a program with fork, and the fork statement can be seen as dividing the program into two parts, A and B. Then the whole program will run as follows:


step1. Suppose that the program is directly executed by the shell, and the process P is generated. P executes all the codes of 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为根的进程树:

640?

验证:


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


程序如下图:

640?wx_fmt=png


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


640?wx_fmt=png


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


总结:


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


Linux云计算免费课程火热开启最后1天免费课程抢先听,运维干货内容免费听点击文末“阅读原文”即可免费听运维课火速抢先~~~~

PS:记得查收小编送你的免费大礼包呦~

福利 | 一万多套PPT模板等你免费来拿!无条件领取!

Free delivery | More than 1000 sets of resume templates are free to get, with a resume making tutorial!

Get it for free | The e-book "100 Cases of Shell Scripts" is free, and it is necessary for operation and maintenance~

640? 640?wx_fmt=jpeg

▼▼Click [ read the original text ] to listen to the 5-day Linux operation and maintenance dry goods sharing class for free , the hot lecture is in progress, come and grab it!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326010255&siteId=291194637