fork原始碼總結

2021-09-11 09:40:46 字數 2559 閱讀 8030

在linux系統下,fork()的實現是通過呼叫clone()實現的,這一呼叫通過不同的引數來指明父子程序之間需要共享的資源。

其中fork、vfork、_clone庫函式都是通過系統呼叫clone(),然後再由clone呼叫do_fork()實現。

dofork()完成了建立的大部分工作,定義在kernel/fork.c中。

首先定義乙個task_struct型別的指標p,每個程序在核心中都有乙個程序控制塊

(pcb)

來維護程序相關的資訊

,linux

核心的程序控制塊是

task_struct

結構體。他會被裝載在

ram中幷包含程序資訊。他會儲存程序的狀態資訊(即每個程序會將其資訊存放在

task_struct

結構體中)。

通過呼叫alloc_pidmap()來為子程序分配乙個新pid。

檢查父程序是否被跟蹤,如果為真,就檢查debugger程式是否想跟蹤子程序,並且子程序不是核心程序(clone_ untraced未設定),那麼就設定clone_ptrace.clone_

untraced

防止程序在子程序上強制執行

clone_ptrace

(繼續除錯子程序)。

呼叫copy_process()函式來複製程序描述符。

呼叫dup_task_struct為子程序建立乙個核心棧、thread_info結構和task_struct這些值與當前程序相同。父子程序此時程序描述符完全相同。

alloc_task_struct巨集為新程序獲取程序描述符。

這裡巨集替換的是kmem_cache_alloc這個函式,定義在slab.c裡,其返回的是__cache_alloc這個函式。

通過alloc_thread_info巨集獲取一塊空閒記憶體區,存放新程序的thread_info結構和核心棧注意這塊記憶體區欄位大小為8kb或4kb。

將父程序的程序描述符複製到tsk所指向的task_struct結構中,並把thread_info置成ti

將父程序的thread_info結構複製到ti中,並將ti_task置成tsk

檢查新建立子程序後,使用者所擁有的程序數目沒有超過可分配數目

然後子程序就要和父程序區分開來,這一階段程序描述符中的很多成員都將被清零或初始化。注意程序描述符的成員不是繼承而來,而是統計資訊。程序描述符中大多數都是共享的

呼叫copy_flags,更新tsk_struct結構中的flags成員,表明程序是否擁有超擁護級許可權,並表明程序還沒有呼叫exec函式的pf_forknoexec標誌被設定

為新程序獲取有效的pid(核心設計第三版中是以getpid的方式獲取有效的pid,這裡應該是通過查詢pidmap圖,來獲取有效的pid)

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

copy_files

拷貝檔案描述符

copy_mm

拷貝記憶體描述符,描述程序位址空間的所以資訊。

用父程序的現場資訊初始化子程序的現場資訊,並將子程序的暫存器的值強制改為0,這就是子程序fork返回為0的原因。

呼叫sched_fork將狀態設定為就緒後讓父子程序平分剩餘的時間片。

最後copy_process返回乙個子程序的指標。

回到dofork後,如果copy_process返回成功,那麼將新程序喚醒並投入執行。

注意核心有意讓子程序優先執行(但事實上並非總是如此),一般子程序都會優先呼叫

exec

函式,避免寫實拷貝的額外開銷。如果父程序優先進行,就會造成位址空間的寫入。

fork原始碼剖析

1.什麼是程序?程序可以理解為正在執行的程式。程序控制塊 pcb 有作業系統建立和管理。程序控制塊是作業系統能夠支援多程序和提供多處理的關鍵工具。2.程序的建立 1 分配pcb 2 分配位址空間 fork 建立新程序 include includepid t fork void fork 函式的每次...

Linux核心 fork 原始碼分析

核心版本 linux 4.4.18 原始碼位置 這裡 接著 呼叫copy process 它設定了程序描述符以及子程序所需的任何其他核心資料結構。ftrace graph init task 初始化ftrace,核心追蹤函式呼叫。rt mutex init task 初始化鎖。copy creds ...

ArrayList原始碼總結

1.1無引數建構函式 public arraylist private static final object empty elementdata public boolean add e e private void ensurecapacityinternal int mincapacity e...