Linux

vfork() 呼叫 SYS_vfork 但 fork() 呼叫 SYS_clone?

  • March 27, 2018

在執行由(版本 5.4.0)ltrace -S編譯的兩個程序後,一個呼叫,一個呼叫,我發現呼叫while呼叫。我在任何地方都找不到有關此特定行為的任何資訊(一些消息來源說每個,並由相應命名的呼叫實現,而其他消息來源說所有三個呼叫都是使用 實現的)。gcc``vfork()``fork()``vfork()``SYS_vfork``fork()``SYS_clone``fork()``vfork()``clone()``sys_``sys_clone

原始碼:

#include<stdio.h>
main()
{
       int pid;
       pid=vfork();
}

輸出ltrace -S

...
__libc_start_main([some stuff here] <unfinished ...>
vfork([more stuff] <unfinished ...>
SYS_vfork([more stuff])
--- SIGCHLD (Child exited) ---

SYS_vforklibc 使用forvfork() 但不使用SYS_forkfor是否有原因fork()?我已經閱讀了Thomas Nyman 對核心中 哪個文件指定 fork(), vfork()… 使用 sys_clone() 系統呼叫的回答,其中說:

vfork()反過來是通過一個單獨的CLONE_VFORK標誌實現的,這將導致父程序休眠,直到子程序通過信號喚醒它。子程序將是父程序命名空間中唯一的執行執行緒,直到它呼叫exec()或退出。不允許孩子寫入記憶體。對應的clone()呼叫可能如下:

clone(CLONE_VFORK | CLONE_VM | SIGCHLD, 0)

這似乎與我觀察到的ltrace -S.

我是不是搞砸了,還是 glibc 的作者故意選擇vfork()使用 usingSYS_vfork而不是SYS_clone出於某種原因?這是否被認為是隨時可能改變的東西,還是我們可以依賴它?

我是不是搞砸了,還是 glibc 的作者故意選擇使用 SYS_vfork 而不是 SYS_clone 來實現 vfork() 是有原因的?

從歷史上看,我認為這更有可能只是vfork不需要更改的結果。兩者vforkfork最初都使用了等效的系統呼叫。當實現 NPTL 執行緒時,實現fork被更改為 useclone,因為C 庫需要重置執行緒 idvfork不需要擔心執行緒,因為它只適用於execve(無論如何都會重置所有狀態),所以它保持不變。

NPTL 設計論文解釋了為什麼在可能使用執行緒時fork系統呼叫不足以實現庫呼叫:fork

為了在沒有記憶體洩漏的情況下實現該功能,有必要回收fork用於堆棧的記憶體和除執行緒呼叫之外的所有執行緒的其他內部資訊。fork在這種情況下,核心無能為力。


這是否被認為是隨時可能改變的東西,還是我們可以依賴它?

由於您使用 C 庫進行 fork,因此您只能依賴 C 庫提供 API 中記錄的行為;您不能依賴特定的實現。您不應該依賴vfork(3)使用vfork(2)系統呼叫來代替clone(2),也不應該依賴fork(3)使用clone(2)來代替fork(2). 請注意,使用的系統呼叫可能因一種架構而異…

如果你真的需要依賴特定的系統呼叫,你應該直接使用那些並放棄 C 庫包裝器。

引用自:https://unix.stackexchange.com/questions/433702