Linux

為什麼 ’ls’ 是由 execve() 呼叫而不是 fork() 創建的

  • April 14, 2021

據我了解,每當您在 shell 中鍵入諸如“ls”之類的命令時,作為我的 shell 的父程序使用 fork() 系統呼叫複制自身,然後使用 exec() 系統呼叫將其替換為新程序,在這種情況下’ls’一旦退出,控制權就會交還給我的shell。

但是,當我在 ’ls’ 上執行 strace 時,我只看到 execve() 呼叫而沒有 fork,並且控制權仍然交還給我的 shell。這裡有點糊塗…

$ strace ls
execve("/usr/bin/ls", ["ls"], 0x7ffd938934e0 /* 25 vars */) = 0
brk(NULL)                               = 0x1134000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6ea9e38000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=23255, ...}) = 0

你的理解是正確的。當你跑步strace ls時,甚至有兩個叉子。shell fork 自己並使用exec()to runstrace和 strace 做同樣的事情 to run ls

您在 strace 輸出中看不到分叉,因為 strace 列印了源自strace 的子程序的所有系統呼叫,並且此時分叉已經發生:

  1. bash分叉和執行strace
  2. strace叉子
  3. strace程序附加到子程序以攔截所有系統呼叫。

從此時起,您只能看到系統呼叫。 4. 孩子使用strace_ls``execve()

查看分叉發生的一種方法是strace“從外部”附加:

  • 用於echo $$獲取shell的程序id
  • 在另一個控制台strace -f --attach=PID中用上面的程序 ID 替換“PID”執行。
  • ls在第一個 shell 中執行
  • 在另一個控制台視窗中,您將看到 shell 中發生的所有系統呼叫和分叉的子項(包括fork()/clone()呼叫)。
  • 在第二個控制台中使用 CTRL+C 停止 strace。

要提到的另一件事是,fork()目前的 Linux 核心是使用clone()系統呼叫實現的,因此您可能會看到clone(…)而不是fork()在 strace 輸出中看到。

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