为什么在终端中键入 '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
时:
- 它调用
fork()
调用系统调用 clone()
的库函数
创建子进程。
- 然后调用系统调用
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
.
- 启动一个 shell,然后获取其 PID(在 bash 中只需
echo $$
即可获取当前的 shell PID)。
- 开始第二个 shell,运行
strace -f -p PID_OF_FIRST_SHELL
。
- 在第一个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} ---
...
我的理解是,当我们在终端输入ls
时:
- 它调用
fork()
调用系统调用clone()
的库函数 创建子进程。 - 然后调用系统调用
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
.
- 启动一个 shell,然后获取其 PID(在 bash 中只需
echo $$
即可获取当前的 shell PID)。 - 开始第二个 shell,运行
strace -f -p PID_OF_FIRST_SHELL
。 - 在第一个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} --- ...