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

cod*_*ver 1 linux ls system-calls linux-kernel strace

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

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

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

可能是什么原因?

我尝试了以下命令:

strace ls
strace -c ls
strace -f ls 
Run Code Online (Sandbox Code Playgroud)

操作系统-红帽

Mar*_*lli 5

确实,您的 shell 使用fork+execve来执行命令,但您没有跟踪您的 shell,因此您不会看到它!

strace工具只是创建一个子级(通过fork),使用所请求的命令附加到它ptrace,然后执行execve请求的命令,因此,如果您执行简单的操作,strace ls您将看到的第一件事就是startexecve完成的操作。stracels

如果您想查看shell 的功能,可以启动一个 shell,然后使用 附加到另一个 shell strace

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

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

strace -e clone,fork,execve -f -p PID_OF_FIRST_SHELL
Run Code Online (Sandbox Code Playgroud)

我的机器上的示例:

  • 外壳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
    
    Run Code Online (Sandbox Code Playgroud)
  • 外壳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} ---
    ...
    
    Run Code Online (Sandbox Code Playgroud)