为什么在终端中键入 'strace ls' 时无法在 strace 输出中查看 clone() 系统调用?

Why am I not able to view the clone() system call in strace output when typing 'strace ls' in terminal?

我的理解是,当我们在终端输入ls时:

  1. 它调用 fork() 调用系统调用 clone() 的库函数 创建子进程。
  2. 然后调用系统调用execve(),用新内容替换新进程的地址space。

在那种情况下,我希望在 strace ls 输出中看到系统调用 clone()execve()。但我只看到 execve() 而不是 clone().

可能是什么原因?

我尝试了以下命令:

strace ls
strace -c ls
strace -f ls 

OS - 红帽

没错,你的shell确实fork+execve执行了一个命令,但是你没有追踪你的shell,所以你不会看到!

strace 工具只是创建一个子项(通过 fork),使用 ptrace 附加到它,然后执行请求命令的 execve,所以如果你做一个简单的 strace ls 您将看到的第一件事是 strace 完成的 execve 开始 ls.

如果您想查看 您的 shell 做了什么,您可以启动一个 shell 然后从另一个 shell 附加到它strace.

  1. 启动一个 shell,然后获取其 PID(在 bash 中只需 echo $$ 即可获取当前的 shell PID)。
  2. 开始第二个 shell,运行 strace -f -p PID_OF_FIRST_SHELL
  3. 在第一个shell中执行ls,在第二个strace中执行strace的输出。

请注意,由于 strace 默认跟踪每个系统调用,并且 shells 通常是非常复杂的程序,您会在输出中看到很多系统调用。如果你只想观察几个系统调用,你可以使用 -e 选项过滤它们,例如:

strace -e clone,fork,execve -f -p PID_OF_FIRST_SHELL

我机器上的例子:

  • Shell 1:

    root@desktop:~/test# echo $$
    30878
    root@desktop:~/test# ls -l
    total 0
    -rw-r--r-- 1 root root 0 Oct 15 00:21 a
    -rw-r--r-- 1 root root 0 Oct 15 00:21 b
    -rw-r--r-- 1 root root 0 Oct 15 00:21 c
    -rw-r--r-- 1 root root 0 Oct 15 00:21 d
    
  • Shell 2:

    root@desktop:~/test# strace -e clone,fork,execve -f -p 30878
    strace: Process 30878 attached
    clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f070ece0a10) = 30958
    strace: Process 30958 attached
    [pid 30958] execve("/bin/ls", ["ls", "--color=auto", "-l"], 0x55c87a5cb9f0 /* 22 vars */) = 0
    [pid 30958] +++ exited with 0 +++
    --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=30958, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
    clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f070ece0a10) = 30959
    strace: Process 30959 attached
    [pid 30959] +++ exited with 0 +++
    --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=30959, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
    ...