天天看點

linux中fork函數執行後父子程序執行的順序,,fork函數的兩次傳回和父子程序的執行順序簡介...

今天為了參加騰訊的面試,特地研究了一下fork的兩次傳回。

大家都知道,調用fork後會傳回兩個值或者一個值。兩個值是指在調用成功的情況下,傳回0表示子程序在運作,大于0的數表示父程序在運作,錯誤情況下就傳回一個值,一個小于0的值。在建立成功的情況下,子程序執行傳回0,是因為一個子程序隻有一個父程序,是以無需知道它父程序的id,通過getppid()也就可以擷取它的值,而父程序運作時,它需要知道它的至此執行對應的子程序是哪個,因為一個父程序可能會有不止一個的子程序,而且在父程序中也沒有可以直接獲得其子程序pid的庫函數。

下面就介紹fork的兩次傳回,一個函數的調用怎麼會傳回兩個值呢,這裡要強調的是,它不是傳回了兩個值,而是傳回了兩次,一次傳回一個值,是以它還是符合函數傳回值的特性---隻能傳回一個值。

fork()是一個經過封裝的使用者态函數,當使用者程式調用了fork函數之後,執行系統調用sys_fork(),而在sys_fork()中直接調用了do_fork()函數,在do_fork()函數中有6個參數,關于參數,我暫不詳解,因為我還沒研究透。也就是說真正的建立程序實在do_fork函數中實作的,其實向vfork,pthread_creat也都是最終調用的do_fork函數,do_fork函數對調用它的函數的差別是通過clone_flags标志來實作的。

long do_fork(unsigned long clone_flags,

unsigned long stack_start,

struct pt_regs *regs,

unsigned long stack_size,

int __user *parent_tidptr,

int __user *child_tidptr)

在do_fork函數中又調用了copy_process函數,在這個函數裡面,先用位圖法的方式給新程序配置設定一個pid,然後再為新程序配置設定PCB資源,先将新程序要複制父程序的資源複制到它的PCB中,然後再為其PCB中的其他變量指派。一般當一個程序的PCB建立好了,這個程序也就存在了,那麼此時已經存在兩個程序了,一個是父程序,一個是新建立的子程序,子程序若執行則傳回0,父程序執行則傳回子程序的pid。是以兩次傳回,指的是子程序和父程序各傳回了一個值。

對于父子程序執行順序的問題:也是在do_fork函數中,它會有一個标志性的變量,根據其不同取值,來決定先讓誰執行,比如子程序先執行然後再把父程序插入到隊列中,具體位置我也沒研究清楚,簡單來說就是在核心的實作過程中,父子程序的執行順序還是由程式本身來決定的,但是到了使用者态看起來就是随機的了。

以上是我個人在看了資料後的了解和總結,可能在細節方面有些問題,歡迎大家指正!