strace
运行指定的命令直到退出。它拦截并记录进程调用的系统调用以及进程接收的信号。
当在 bash shell 中运行外部命令时,shell 首先fork()
是子进程,然后是execve()
子进程中的命令。所以我想这strace
会报告fork()
或类似的东西,例如clone()
但下面的例子表明事实并非如此。为什么在命令之前不strace
报告父 shell 是fork()
子进程?execve()
谢谢。
$ strace -f time
execve("/usr/bin/time", ["time"], [/* 66 vars */]) = 0
brk(0) = 0x84c000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efe9b2a5000
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=141491, ...}) = 0
mmap(NULL, 141491, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7efe9b282000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\320\37\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1840928, ...}) = 0
mmap(NULL, 3949248, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7efe9acc0000
mprotect(0x7efe9ae7b000, 2093056, PROT_NONE) = 0
mmap(0x7efe9b07a000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7efe9b07a000
mmap(0x7efe9b080000, 17088, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7efe9b080000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efe9b281000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efe9b27f000
arch_prctl(ARCH_SET_FS, 0x7efe9b27f740) = 0
mprotect(0x7efe9b07a000, 16384, PROT_READ) = 0
mprotect(0x602000, 4096, PROT_READ) = 0
mprotect(0x7efe9b2a7000, 4096, PROT_READ) = 0
munmap(0x7efe9b282000, 141491) = 0
write(2, "Usage: time [-apvV] [-f format] "..., 177Usage: time [-apvV] [-f format] [-o file] [--append] [--verbose]
[--portability] [--format=format] [--output=file] [--version]
[--quiet] [--help] command [arg...]
) = 177
exit_group(1) = ?
+++ exited with 1 +++
答案1
$ strace -f time
execve("/usr/bin/time", ["time"], [/* 66 vars */]) = 0
brk(0) = 0x84c000
...
strace直接调用被跟踪的程序。它不使用 shell 来运行子命令,除非子命令是shell 调用。这里事件的大致顺序如下:
- shell
strace
使用参数“strace”、“-f”、“time”执行。 - Strace 启动,解析其命令行,并最终分叉。
- 原始(父)strace 进程开始跟踪子strace 进程。
- 子 strace 进程
/usr/bin/time
使用参数“time”执行。 - 时间程序启动。
在第1步之后,原来的shell进程处于空闲状态,等待strace退出。它没有主动做任何事情。即使它正在做某事,strace 也不会跟踪它,因此它的活动不会出现在 strace 输出中。
答案2
有问题fork
的是启动机制的一部分strace
;当追踪开始时它已经结束。