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