linux子程序執行起點

2021-08-03 06:58:54 字數 3437 閱讀 1445

參考部落格

首先給出結論:

子程序繼承了父程序的程式計數器的

當前值,也就是繼承了fork()語句執行時父程序當前的環境,而不是程式的初始環境,所以子程序從fork()語句之後開始執行。

fork呼叫的乙個奇妙之處就是它僅僅被呼叫一次,卻能夠返回兩次,它可能有三種不同的返回值:

1)在父程序中,fork返回新建立子程序的程序id;

2)在子程序中,fork返回0;

3)如果出現錯誤,fork返回乙個負值;

(注意,這裡所說的返回兩個值只是在呼叫fork函式時的特性,實際上,子程序有自己的程序號,通過 getpid() 函式得到的就是真實的程序號,並不等於0)

建立新程序成功後,系統中出現兩個基本完全相同的程序,這兩個程序執行沒有固定的先後順序,哪個程序先執行要看系統的程序排程策略。此時,兩個程序都從fork開始往下執行,只是pid不同。

程序複製時還有兩個知識點:

1) linux下乙個程序在記憶體裡有三部分的資料,就是"**段"、"堆疊段"和"資料段"。

"**段",顧名思義,就是存放了程式**的資料,假如機器中有數個程序執行相同的乙個程式,那麼它們就可以使用相同的**段。

"堆疊段"存放的就是子程式的返回位址、子程式的引數以及程式的區域性變數。

「資料段」則存放程式的全域性變數,常數以及動態資料分配的資料空間(比如用malloc之類的函式取得的空間)。

父程序和子程序共用「**段」,而「堆疊段」和「資料段」不能共用,需要拷貝複製。

一般cpu都是以"頁"為單位來分配記憶體空間的,每乙個頁都是實際物理記憶體的乙個映像,象intel的cpu,其一頁在通常情況下是4086位元組大小,而無論是資料段還是堆疊段都是由許多"頁"構成的,fork函式複製這兩個段,只是"邏輯"上的,並非"物理"上的,也就是說,實際執行fork時,物理空間上兩個程序的「資料段」和「堆疊段」都還是共享著的,當有乙個程序寫了某個資料時,這時兩個程序之間的資料才有了區別,系統就將有區別的"頁"從物理上也分開,也叫寫時複製技術(copy-on-write)。系統在空間上的開銷就可以達到最小。

2)   函式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返回。

這裡可以看出

parent process

執行了printf("hello!\n"); 

而child process

沒有執行

printf("hello!\n"); 

有乙個讓人很迷惑的例子:

#include #include main () 

此時列印輸出了兩個fork!這不免讓人以為是child process從#include處開始執行,所以也執行了printf("fork!"); 語句。

其實不然,出現這種問題的原因在於:

這就跟printf

的緩衝機制有關了

,printf

某些內容時

,作業系統僅僅是把該內容放到了

stdout

的緩衝佇列裡了

,並沒有實際的寫到螢幕上

。但是,

只要看到有

\n,則會立即重新整理

stdout,

因此就馬上能夠列印了.

mian

函式(parent process)

執行了printf("fork!")

後, "fork!"

僅僅被放到了緩衝裡

,再執行到

fork時,

緩衝裡面的

aaaaaa

被子程序

(child process)

繼承了,

因此在子進程度

stdout

緩衝裡面就也有了

"fork!"

。所以,

你最終看到的會是

"fork!" 

被printf了2

次!!!! 

而mian

函式(parent process)

執行printf("fork!\n")

後,"fork!" 

被立即列印到了螢幕上,之後

fork

到的子程序

(child process)

裡的stdout

緩衝裡不會有

"fork!"

內容因此你看到的結果會是

"fork!" 

被printf了1

次!!!!

Linux 建立子程序執行任務

linux 作業系統緊緊依賴程序建立來滿足使用者的需求。例如,只要使用者輸入一條命令,shell 程序就建立乙個新程序,新程序執行 shell 的另乙個拷貝並執行使用者輸入的命令。linux 系統中通過 fork vfork 系統呼叫來建立新程序。本文將介紹如何使用 fork vfork 系統呼叫來...

Linux 建立子程序執行任務的實現方法

linux 作業系統緊緊依賴程序建立來滿足使用者的需求。例如,只要使用者輸入一條命令,shell 程序就建立乙個新程序,新程序執行 shell 的另乙個拷貝並執行使用者輸入的命令。linux 系統中通過 fork vfork 系統呼叫來建立新程序。本文將介紹如何使用 fork vfork 系統呼叫來...

linux建立子程序

include include include intmain int argc,char ar else if pid 0 else if pid 0 return0 include include include intmain int argc,char ar else if pid 0 el...