strace是用来跟踪系统调用的,这里只研究一个问题:
在一个系统调用返回之前,系统调用的参数是否会被显示出来。
测试1:
1 2 |
<?php sleep(20000); |
strace 跟踪的部分信息:
1 2 3 4 5 |
munmap(0xb7d7e000, 4096) = 0 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 nanosleep({10000, 0}, <unfinished ...> |
我们发现,系统调用nanosleep的第一个参数显示出来了,nanosleep的函数签名如下:
1 |
int nanosleep(const struct timespec *req, struct timespec *rem); |
通过对该系统调用的了解,我们发现,第一个参数是要sleep多长时间,而且是const的,不会被修改,所以,在系统调用开始就确定了,所以可以直接显示出来,而第二个参数的含义是: 如果该系统调用因为接收到信号而被迫返回,则第二个参数为该系统调用还剩余的sleep的时间,这个时间只有到该系统调用完成才能确定的,所以,不能立即显示出来。
再举个例子吧:
比如connect系统调用:
1 2 3 |
# strace nc 10.23.33.55 234 ... connect(3, {sa_family=AF_INET, sin_port=htons(234), sin_addr=inet_addr("10.23.33.55")}, 16 <unfinished ...> |
上面是一个不存在的IP地址,所以连接不上的,导致connect阻塞,我们发现,在connect返回之前,我们已经知道3个参数信息(实际上一共也就3个参数),参数的显示能给我们很有用的信息(IP、Port)。
在比如poll系统调用:
1 2 |
<?php file_get_contents("http://10.22.33.44/"); |
跟踪结果:
1 2 3 4 5 6 7 |
#strace test.php ... socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3 fcntl64(3, F_GETFL) = 0x2 (flags O_RDWR) fcntl64(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 connect(3, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("10.22.33.44")}, 16) = -1 EINPROGRESS (Operation now in progress) poll( <unfinished ...> |
poll的函数签名如下:
1 |
int poll(struct pollfd *ufds, unsigned int nfds, int timeout); |
我们发现poll有3个参数,但是在poll返回之前,一个参数信息都没有给出,这是因为第一个参数的值需要等到poll返回才能确定,如果我们strace发现一个已经运行这的进程在poll时阻塞了,将很难知道是哪个文件描述符上阻塞的。