關於linux下fork 的底層實現 詳解

2021-07-23 22:13:40 字數 2228 閱讀 5444

fork()系統呼叫通過複製乙個現有程序來建立乙個全新的程序(程序的另外乙個名字叫做任務)。

程序存放在乙個叫做任務佇列雙向迴圈鍊錶中。

鍊錶中的每一項都是型別為task_struct稱為程序描述符的結構。(它包含乙個具體程序的所有資訊)

程序描述符的存放:

核心通過乙個唯一的程序標識值pid來標識每個程序。//最大值預設為32768,short int短整型的最大值,它就是系統中允許同時存在的程序的最大數目

程序狀態

(1)task_running(執行)

(2)task_interruptible(可中斷)

(3)task_uninterruptible(不可中斷)

(4)task_zombie(僵死)

(5)task_stopped(停止)

fork():

父子程序區別

子程序和父程序的區別僅僅在於pid,ppid,某些資源統計量(掛起的訊號,沒有必要被繼承)

寫時拷貝(個人認為很重要)

linux的fork()使用寫時拷貝頁實現。

寫時拷貝:一種可以推遲甚至免除拷貝資料的技術

使用寫時拷貝,核心並不複製整個程序位址空間,而是讓父子程序共享同乙個拷貝。只有需要寫入的時候,資料才會被複製,從而各個程序擁有各自的拷貝。

資源的複製只有在需要寫入的時候才進行,在這之前只是以唯讀方式共享,本質是將位址空間上的頁的拷貝推遲到實際發生寫入的時候

fork()的實際開銷:賦值父程序的頁表(頁表是一種特殊的資料結構,放在系統空間的頁表區,存放邏輯頁與物理頁幀的對應關係)以及給子程序建立唯一的程序描述符。

(一般情況下,程序建立後都會馬上執行乙個可執行的檔案。)

實現:

linux通過clone()系統呼叫實現fork()。

fork(),vfork(),和_clone()庫函式都根據各自需要的引數標誌去呼叫clone(),然後由clone()去呼叫do_fork()

do_fork()完成了建立中的大部分工作,它定義在kernel/fork.c中。該函式呼叫copy_process(),接下來copy_process()實現的工作如下

1.呼叫dup_task_struct()為新程序建立乙個核心棧,threaad_info結構和task_struct,這些值與當前程序的值相同。此時,子程序和父程序的描述符是完全相同的。

2.檢查新建立的這個子程序後,當前使用者所擁有的程序數目沒有超出給他分配的資源的限制。

3.現在,子程序著手使自己與父程序區別拷來。程序描述符內的許多成員都要被清0或設為初始值。程序描述符的成員值並不是繼承而來的,而主要是統計資訊,程序描述符中大多數的資料都是共享的。

4.接下來,子程序的狀態被設定為task_uninterruptible(不可中斷)以保證它不會投入執行。

5.copy_process()呼叫copy_flags()以更新task_struct的flags成員。表明程序是否擁有超級使用者許可權的pf_superpriv標誌被清0.表名程序還沒有呼叫exec()函式的pf_forknoexec標誌被設定。

6.呼叫get_pid()為新程序獲取乙個有效的pid

7.根據傳遞給clone()的引數標誌,copy_process()拷貝或共享開啟的檔案,檔案系統資訊,訊號處理函式,程序位址空間和命名空間等。在一般情況下,這些資源會被給定程序的所有執行緒共享;否則,這些資源對每個程序是不同的,因此被拷貝到這裡。

8.讓父程序和子程序平分剩餘的時間片

9.最後copy_process()做掃尾工作並返回乙個指向子程序的指標

再回到do_fork()函式,如果copy_process函式成功返回,新建立的子程序被喚醒並讓其投入執行。核心有意選擇子程序首先執行。因為一般子程序都會馬上呼叫exec()函式,這樣可以避免寫時拷貝的額外開銷,如果父程序首先執行的話,有可能會開始向位址空間寫入。

Linux下的fork 函式

fork fork的英文翻譯是 分叉 同樣在linux中我們也可以理解為如果使用了fork 函式,程序也會 分叉 下面進行具體的說明fork 函式。定義 通過系統呼叫建立乙個與原程序幾乎完全相同的程序,其中新產生的程序成為子程序。原型 pid t fork void fid t相當於int型別特殊之...

linux下fork的使用

需要包含標頭檔案 include include 函式宣告 pid t fork void 其中pid t在sys types.h中定義 typedef pid t pid t 可以看到只是乙個int.fork 通過複製呼叫過程來建立乙個新過程。新程序稱為子程序,與呼叫程序 稱為父程序 完全相同,但...

linux下fork的問題

題目 請問下面的程式一共輸出多少個 include include include int main void return0 如果你對 fork 的機制比較熟悉的話,這個題並不難,輸出應該是 6 個 但是,實際上這個程式會很 tricky 地輸出 8 個 要講清這個題,我們首先需要知道 fork ...