日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

發(fā)布時間:2023/12/2 linux 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 机制 linux_从一道面试题谈linux下fork的运行机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天一位朋友去一個不錯的外企面試linux開發(fā)職位,面試官出了一個如下的題目:

給出如下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);

}

要求如下:

已知從這個程序執(zhí)行到這個程序的所有進程結束這個時間段內,沒有其它新進程執(zhí)行。

1、請說出執(zhí)行這個程序后,將一共運行幾個進程。

2、如果其中一個進程的輸出結果是“pid1:1001, pid2:1002”,寫出其他進程的輸出結果(不考慮進程執(zhí)行順序)。

明顯這道題的目的是考察linux下fork的執(zhí)行機制。下面我們通過分析這個題目,談談linux下fork的運行機制。

預備知識

這里先列出一些必要的預備知識,對linux下進程機制比較熟悉的朋友可以略過。

1、進程可以看做程序的一次執(zhí)行過程。在linux下,每個進程有唯一的PID標識進程。PID是一個從1到32768的正整數,其中1一般是特殊進程init,其它進程從2開始依次編號。當用完32768后,從2重新開始。

2、linux中有一個叫進程表的結構用來存儲當前正在運行的進程。可以使用“ps aux”命令查看所有正在運行的進程。

3、進程在linux中呈樹狀結構,init為根節(jié)點,其它進程均有父進程,某進程的父進程就是啟動這個進程的進程,這個進程叫做父進程的子進程。

4、fork的作用是復制一個與當前進程一樣的進程。新進程的所有數據(變量、環(huán)境變量、程序計數器等)數值都和原進程一致,但是是一個全新的進程,并作為原進程的子進程。

解題的關鍵

有了上面的預備知識,我們再來看看解題的關鍵。我認為,解題的關鍵就是要認識到fork將程序切成兩段。看下圖:

上圖表示一個含有fork的程序,而fork語句可以看成將程序切為A、B兩個部分。然后整個程序會如下運行:

step1、設由shell直接執(zhí)行程序,生成了進程P。P執(zhí)行完Part. A的所有代碼。

step2、當執(zhí)行到pid = fork();時,P啟動一個進程Q,Q是P的子進程,和P是同一個程序的進程。Q繼承P的所有變量、環(huán)境變量、程序計數器的當前值。

step3、在P進程中,fork()將Q的PID返回給變量pid,并繼續(xù)執(zhí)行Part. B的代碼。

step4、在進程Q中,將0賦給pid,并繼續(xù)執(zhí)行Part. B的代碼。

這里有三個點非常關鍵:

1、P執(zhí)行了所有程序,而Q只執(zhí)行了Part. B,即fork()后面的程序。(這是因為Q繼承了P的PC-程序計數器)

2、Q繼承了fork()語句執(zhí)行時當前的環(huán)境,而不是程序的初始環(huán)境。

3、P中fork()語句啟動子進程Q,并將Q的PID返回,而Q中的fork()語句不啟動新進程,僅將0返回。

解題

下面利用上文闡述的知識進行解題。這里我把兩個問題放在一起進行分析。

1、從shell中執(zhí)行此程序,啟動了一個進程,我們設這個進程為P0,設其PID為XXX(解題過程不需知道其PID)。

2、當執(zhí)行到pid1 = fork();時,P0啟動一個子進程P1,由題目知P1的PID為1001。我們暫且不管P1。

3、P0中的fork返回1001給pid1,繼續(xù)執(zhí)行到pid2 = fork();,此時啟動另一個新進程,設為P2,由題目知P2的PID為1002。同樣暫且不管P2。

4、P0中的第二個fork返回1002給pid2,繼續(xù)執(zhí)行完后續(xù)程序,結束。所以,P0的結果為“pid1:1001, pid2:1002”。

5、再看P2,P2生成時,P0中pid1=1001,所以P2中pid1繼承P0的1001,而作為子進程pid2=0。P2從第二個fork后開始執(zhí)行,結束后輸出“pid1:1001, pid2:0”。

6、接著看P1,P1中第一條fork返回0給pid1,然后接著執(zhí)行后面的語句。而后面接著的語句是pid2 = fork();執(zhí)行到這里,P1又產生了一個新進程,設為P3。先不管P3。

7、P1中第二條fork將P3的PID返回給pid2,由預備知識知P3的PID為1003,所以P1的pid2=1003。P1繼續(xù)執(zhí)行后續(xù)程序,結束,輸出“pid1:0, pid2:1003”。

8、P3作為P1的子進程,繼承P1中pid1=0,并且第二條fork將0返回給pid2,所以P3最后輸出“pid1:0, pid2:0”。

9、至此,整個執(zhí)行過程完畢。

所得答案:

1、一共執(zhí)行了四個進程。(P0, P1, P2, P3)

2、另外幾個進程的輸出分別為:

pid1:1001, pid2:0

pid1:0, pid2:1003

pid1:0, pid2:0

進一步可以給出一個以P0為根的進程樹:

驗證

下面我們去linux下實際執(zhí)行這個程序,來驗證我們的答案。

程序如下圖:

用gcc編譯、執(zhí)行后結果如下:

由于我們不太可能剛巧碰上PID分配到1001的情況,所以具體數值可能和答案有所差別。不過將這里的2710看做基數的話,結果和我們上面的解答是一致的。

總結

應該說這不是一道特別難或特別刁鉆的題目,但是由于fork函數運行機制的復雜性,造就了當兩個fork并排時,問題就變得很復雜。解這個題的關鍵,一是要對linux下進程的機制有一定認識,二是抓住上文提到的幾個關于fork的關鍵點。朋友說,這個題給的時間是5分鐘,應該說時間還算充裕,但是在面試的場合下,還是很考驗一個人對進程、fork的掌握程度和現場推理能力。

希望本文能幫助朋友們對fork的執(zhí)行機制有一個明晰的認識。

更多干貨資料點擊這里

總結

以上是生活随笔為你收集整理的机制 linux_从一道面试题谈linux下fork的运行机制的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。