fork系統呼叫的執行過程

2021-07-03 23:36:59 字數 3900 閱讀 6723

1.linux提供了三個系統呼叫用於建立程序,分別是fork,vfork,clone:

fork系統呼叫:核心採用寫時複製技術對傳統的fork函式進行了下面的優化.即子程序建立後,父子程序以唯讀的方式共享父程序的資源(並不包括父程序的頁表項).當子程序需要修改程序位址空間的某一頁時,才為子程序複製該頁.採用這樣的技術可以避免對父程序中某些資料不必要的複製.

vfork系統呼叫:使用vfork函式建立的子程序會完全共享父程序的位址空間,包括父程序的頁表項.父子程序任意一方對任何資料的修改使得另一方都可以感知到.為了使得雙方不受這種影響,vfork函式建立了子程序後,父程序便被阻塞,直至子程序呼叫了exec()或exit().由於現在fork函式引入了寫時複製技術,在不考慮複製父程序頁表項的情況下,vfork函式幾乎不會被使用.

clone系統呼叫:clone函式建立子程序時靈活度比較大,因為它可以通過傳遞不同的引數來選擇性的複製父程序的資源.

系統呼叫fork,vfork和clone在核心中對應的服務例程分別為sys_fork(),sys_vfork()和sys_clone():

asmlinkage int sys_fork(struct pt_regs regs)

asmlinkage int sys_clone(struct pt_regs regs)

asmlinkage int sys_vfork(struct pt_regs regs)

可以看到do_fork()均被上述三個服務例程呼叫.三個系統呼叫的執行過程如下圖所示:

2.do_fork()函式的引數解釋:

do_fork()函式的原型:

long do_fork(unsigned

long clone_flags,

unsigned

long stack_start,

unsigned

long stack_size,

int __user *parent_tidptr,

int __user *child_tidptr)

clone_flags:該標誌位的4個位元組分為兩部分.最低的乙個位元組為子程序結束時傳送給父程序的訊號**,通常為sigchld(用於wait系統呼叫).剩餘的三個位元組則是各種clone標誌的組合.通過clone標誌可以有選擇的對父程序的資源進行複製.

statck_start:子程序使用者態堆疊的位址

stack_size:未被使用,通常被賦值為0

3.do_fork()函式 部分**:

long do_fork(unsigned

long clone_flags,

unsigned

long stack_start,

unsigned

long stack_size,

int __user *parent_tidptr,

int __user *child_tidptr)

p = copy_process(clone_flags, stack_start, stack_size,

child_tidptr, null, trace); //得到乙個程序描述符, 核心棧, thread_info與父程序一樣的子程序描述符

if (!is_err(p))

wake_up_new_task(p); //將子程序加入紅黑樹, 並判斷子程序是否可以搶占父程序, 此時子程序已經處於執行狀態

if (unlikely(trace))

ptrace_event(trace, nr);

//如果設定了clone_vfork標誌, 則父程序使用完成變數阻塞, 直到子程序呼叫exec或exit

if (clone_flags & clone_vfork)

} else

return nr; //返回子程序的程序描述符

}

4.copy_process()函式 部分**:

static

struct task_struct *copy_process(unsigned

long clone_flags,

unsigned

long stack_start,

unsigned

long stack_size,

int __user *child_tidptr,

struct pid *pid,

int trace)

p = dup_task_struct(current); //新建立乙個程序描符, 執行緒描述符, 核心棧

//此時父子程序的內容完全一樣, 接下來就是重新設定一些子程序的值了

//判斷系統中的程序數是不是超過了限制

if (nr_threads >= max_threads)

goto bad_fork_cleanup_count;

copy_flags(clone_flags, p); //將clone_flags複製給子程序

sched_fork(clone_flags, p); //該函式呼叫task_fork_fair函式, 設定子程序的vruntime值

//根據clone_flags值, 拷貝或共享父子程序之間的一些資料結構

retval = perf_event_init_task(p);

retval = audit_alloc(p);

retval = copy_semundo(clone_flags, p);

retval = copy_files(clone_flags, p); //檔案描述符

retval = copy_fs(clone_flags, p); //程序當前工作目錄資訊

retval = copy_sighand(clone_flags, p); //訊號處理表

retval = copy_signal(clone_flags, p); //訊號值的處理

retval = copy_mm(clone_flags, p); //記憶體描述符

retval = copy_namespaces(clone_flags, p); //命名空間

retval = copy_io(clone_flags, p);

retval = copy_thread(clone_flags, stack_start, stack_size, p); //dup_task_struct函式中會在建立子程序的程序描符之前, 把父程序此時的暫存器環境儲存在父程序的核心棧中, 子程序的核心棧再複製父程序的核心棧值, 此函式就是用這些值更新子程序暫存器的值. 另外, 子程序對應的thread_info結構中的esp欄位會被初始化為子程序核心棧的基址

if (pid != &init_struct_pid)

return pid;

}

5.dup_task_struct()函式 部分**:

static

struct task_struct *dup_task_struct(struct task_struct *orig)

本文引述自:

fork系統呼叫過程

又是查詢資料,又是看原始碼,折騰了大半天,終於把fork的過程弄完了,但是後面的跟蹤狀態還不太懂,等具體後面弄清楚了,再加上。核心是2.6.11版本的。fork 系統呼叫 我們執行乙個系統呼叫時,系統將呼叫巨集指令 syscall0 define syscall0 type,name type na...

系統呼叫fork

fork的基本內容 fork是依次呼叫兩次返回,分別返回在父程序和子程序中 1 在父程序中,fork返回新建立子程序的程序id 2 在子程序中,fork返回0 3 如果出現錯誤,fork則返回乙個負值 例子 void fork0 else 在這段 中,fork 被執行後將建立與父程序相同的子程序,並...

linux 系統呼叫執行過程

簡單總結一下linux的系統呼叫過程 層次如下 使用者程式 c庫 即api int 0x80 system call 系統呼叫服務例程 核心程式 先說明一下,我們常說的使用者api其實就是系統提供的c庫。系統呼叫是通過軟中斷指令 int 0x80 實現的,而這條int 0x80指令就被封裝在c庫的函...