自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

從一道面試題談Linux下fork的運(yùn)行機(jī)制

系統(tǒng) Linux
一個(gè)不錯(cuò)的外企面試Linux開發(fā)職位,應(yīng)該說不是一道特別難或特別刁鉆的題目,但是由于fork函數(shù)運(yùn)行機(jī)制的復(fù)雜性,造就了當(dāng)兩個(gè)fork并排時(shí),問題就變得很復(fù)雜。解這個(gè)題的關(guān)鍵,一是要對linux下進(jìn)程的機(jī)制有一定認(rèn)識(shí),二是抓住上文提到的幾個(gè)關(guān)于fork的關(guān)鍵點(diǎn)。

[[227280]]

一個(gè)不錯(cuò)的外企面試Linux開發(fā)職位,面試官出了一個(gè)如下的題目:

從一道面試題談Linux下fork的運(yùn)行機(jī)制

給出如下C程序,在linux下使用gcc編譯:

已知從這個(gè)程序執(zhí)行到這個(gè)程序的所有進(jìn)程結(jié)束這個(gè)時(shí)間段內(nèi),沒有其它新進(jìn)程執(zhí)行。

  1. 請說出執(zhí)行這個(gè)程序后,將一共運(yùn)行幾個(gè)進(jìn)程。
  2. 如果其中一個(gè)進(jìn)程的輸出結(jié)果是“pid1:1001, pid2:1002”,寫出其他進(jìn)程的輸出結(jié)果(不考慮進(jìn)程執(zhí)行順序)。

明顯這道題的目的是考察linux下fork的執(zhí)行機(jī)制。下面我們通過分析這個(gè)題目,談?wù)凩inux下fork的運(yùn)行機(jī)制。

預(yù)備知識(shí):

這里先列出一些必要的預(yù)備知識(shí),對Linux下進(jìn)程機(jī)制比較熟悉的朋友可以略過。

  1. 進(jìn)程可以看做程序的一次執(zhí)行過程。在Linux下,每個(gè)進(jìn)程有唯一的PID標(biāo)識(shí)進(jìn)程。PID是一個(gè)從1到32768的正整數(shù),其中1一般是特殊進(jìn)程init,其它進(jìn)程從2開始依次編號(hào)。當(dāng)用完32768后,從2重新開始。
  2. Linux中有一個(gè)叫進(jìn)程表的結(jié)構(gòu)用來存儲(chǔ)當(dāng)前正在運(yùn)行的進(jìn)程。可以使用“ps aux”命令查看所有正在運(yùn)行的進(jìn)程。
  3. 進(jìn)程在Linux中呈樹狀結(jié)構(gòu),init為根節(jié)點(diǎn),其它進(jìn)程均有父進(jìn)程,某進(jìn)程的父進(jìn)程就是啟動(dòng)這個(gè)進(jìn)程的進(jìn)程,這個(gè)進(jìn)程叫做父進(jìn)程的子進(jìn)程。
  4. fork的作用是復(fù)制一個(gè)與當(dāng)前進(jìn)程一樣的進(jìn)程。新進(jìn)程的所有數(shù)據(jù)(變量、環(huán)境變量、程序計(jì)數(shù)器等)數(shù)值都和原進(jìn)程一致,但是是一個(gè)全新的進(jìn)程,并作為原進(jìn)程的子進(jìn)程。

解題的關(guān)鍵:

有了上面的預(yù)備知識(shí),我們再來看看解題的關(guān)鍵。我認(rèn)為,解題的關(guān)鍵就是要認(rèn)識(shí)到fork將程序切成兩段??聪聢D:

從一道面試題談Linux下fork的運(yùn)行機(jī)制

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

  • step1、設(shè)由shell直接執(zhí)行程序,生成了進(jìn)程P。P執(zhí)行完P(guān)art. A的所有代碼。
  • step2、當(dāng)執(zhí)行到pid = fork();時(shí),P啟動(dòng)一個(gè)進(jìn)程Q,Q是P的子進(jìn)程,和P是同一個(gè)程序的進(jìn)程。Q繼承P的所有變量、環(huán)境變量、程序計(jì)數(shù)器的當(dāng)前值。
  • step3、在P進(jìn)程中,fork()將Q的PID返回給變量pid,并繼續(xù)執(zhí)行Part. B的代碼。
  • step4、在進(jìn)程Q中,將0賦給pid,并繼續(xù)執(zhí)行Part. B的代碼。

這里有三個(gè)點(diǎn)非常關(guān)鍵:

  1. P執(zhí)行了所有程序,而Q只執(zhí)行了Part. B,即fork()后面的程序。(這是因?yàn)镼繼承了P的PC-程序計(jì)數(shù)器)
  2. Q繼承了fork()語句執(zhí)行時(shí)當(dāng)前的環(huán)境,而不是程序的初始環(huán)境。
  3. P中fork()語句啟動(dòng)子進(jìn)程Q,并將Q的PID返回,而Q中的fork()語句不啟動(dòng)新進(jìn)程,僅將0返回。

解題:

下面利用上文闡述的知識(shí)進(jìn)行解題。這里我把兩個(gè)問題放在一起進(jìn)行分析。

  1. 從shell中執(zhí)行此程序,啟動(dòng)了一個(gè)進(jìn)程,我們設(shè)這個(gè)進(jìn)程為P0,設(shè)其PID為XXX(解題過程不需知道其PID)。
  2. 當(dāng)執(zhí)行到pid1 = fork();時(shí),P0啟動(dòng)一個(gè)子進(jìn)程P1,由題目知P1的PID為1001。我們暫且不管P1。
  3. P0中的fork返回1001給pid1,繼續(xù)執(zhí)行到pid2 = fork();,此時(shí)啟動(dòng)另一個(gè)新進(jìn)程,設(shè)為P2,由題目知P2的PID為1002。同樣暫且不管P2。
  4. P0中的第二個(gè)fork返回1002給pid2,繼續(xù)執(zhí)行完后續(xù)程序,結(jié)束。所以,P0的結(jié)果為“pid1:1001, pid2:1002”。
  5. 再看P2,P2生成時(shí),P0中pid1=1001,所以P2中pid1繼承P0的1001,而作為子進(jìn)程pid2=0。P2從第二個(gè)fork后開始執(zhí)行,結(jié)束后輸出“pid1:1001, pid2:0”。
  6. 接著看P1,P1中***條fork返回0給pid1,然后接著執(zhí)行后面的語句。而后面接著的語句是pid2 = fork();執(zhí)行到這里,P1又產(chǎn)生了一個(gè)新進(jìn)程,設(shè)為P3。先不管P3。
  7. P1中第二條fork將P3的PID返回給pid2,由預(yù)備知識(shí)知P3的PID為1003,所以P1的pid2=1003。P1繼續(xù)執(zhí)行后續(xù)程序,結(jié)束,輸出“pid1:0, pid2:1003”。
  8. P3作為P1的子進(jìn)程,繼承P1中pid1=0,并且第二條fork將0返回給pid2,所以P3***輸出“pid1:0, pid2:0”。
  9. 至此,整個(gè)執(zhí)行過程完畢。

所得答案:

1、一共執(zhí)行了四個(gè)進(jìn)程。

  1. (P0, P1, P2, P3) 

2、另外幾個(gè)進(jìn)程的輸出分別為:

 

  1. pid1:1001, pid2:0  
  2. pid1:0, pid2:1003  
  3. pid1:0, pid2:0 

進(jìn)一步可以給出一個(gè)以P0為根的進(jìn)程樹:

從一道面試題談Linux下fork的運(yùn)行機(jī)制

驗(yàn)證:

下面我們?nèi)inux下實(shí)際執(zhí)行這個(gè)程序,來驗(yàn)證我們的答案。

程序如下圖:

從一道面試題談Linux下fork的運(yùn)行機(jī)制

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

從一道面試題談Linux下fork的運(yùn)行機(jī)制

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

總結(jié):

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

責(zé)任編輯:未麗燕 來源: Linux云計(jì)算數(shù)據(jù)自學(xué)
相關(guān)推薦

2021-03-27 10:59:45

JavaScript開發(fā)代碼

2024-10-11 17:09:27

2021-04-13 08:50:21

JS作用域面試題

2011-05-23 11:27:32

面試題面試java

2018-03-06 15:30:47

Java面試題

2009-08-11 10:12:07

C#算法

2023-02-04 18:24:10

SeataJava業(yè)務(wù)

2009-08-11 14:59:57

一道面試題C#算法

2021-05-31 07:55:44

smartRepeatJavaScript函數(shù)

2009-08-11 15:09:44

一道面試題C#算法

2017-11-21 12:15:27

數(shù)據(jù)庫面試題SQL

2022-04-08 07:52:17

CSS面試題HTML

2023-08-01 08:10:46

內(nèi)存緩存

2021-03-16 05:44:26

JVM面試題運(yùn)行時(shí)數(shù)據(jù)

2021-10-28 11:40:58

回文鏈表面試題數(shù)據(jù)結(jié)構(gòu)

2022-02-08 18:09:20

JS引擎解析器

2011-03-02 10:58:16

SQL server入門面試題

2015-09-02 14:09:19

面試題程序設(shè)計(jì)

2017-03-10 09:33:16

JavaScript類型

2017-09-13 07:15:10

Python讀寫文件函數(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)