strace

1.功能介绍:
在理想世界里,每当一个程序不能正常执行一个功能时,它就会给出一个有用的错误提示,告诉你在足够的改正错误的线索。但遗憾的是,我们不是生活在理想世界 里,起码不总是生活在理想世界里。有时候一个程序出现了问题,你无法找到原因,这就是调试程序出现的原因。strace是一个必不可少的调试工具,strace用来监视系统调用。你不仅可以调试一个新开始的程序,也可以调试一个已经在运行的程序(把strace绑定到一个已有的PID上 面),而 ltrace(library call tracer)是一个执行指定的命令直到该命令结束,他会拦截和记录动态链接库的函数,和该进程接受到的信号,他也可以拦截该程序调用的系统函数。
2.常用参数:
-f :除了跟踪当前进程外,还跟踪其子进程。
-F :尝试跟踪vfork调用

-o :将输出信息写到文件file中,而不是显示到标准错误输出(stderr)。
-p :绑定到一个由pid对应的正在运行的进程。此参数常用来调试后台进程。

-T  :记录各个系统调用花费的时间,精确到微秒
-r  :以第一个系统调用(通常为execve)计时,精确到微秒
-e expr : 只会记录指定的调用函数    
3.命令举例:
strace -f -o vim.strace vim: 跟踪vim及其子进程的运行,将输出信息写到文件vim.strace。
ltrace -p 234: 跟踪一个pid为234的已经在运行的进程。
strace -o output.txt -T -tt -e trace=all -p 28979
上面的含义是 跟踪28979进程的所有系统调用(-e trace=all),并统计系统调用的花费时间,以及开始时间(并以可视化的时分秒格式显示),最后将记录结果存在output.txt文件里面。
4.示例代码与分析:

int main(int argc, char** argv)
{
    getpid(); //该系统调用起到标识作用
    if(argc < 2)
    {
        printf("hang (user|system)\n");
        return 1;
    }
    if(!strcmp(argv[1], "user"))
        while(1);
    else if(!strcmp(argv[1], "system"))
        sleep(500);
    return 0;
}

a.用户态挂死跟踪输出:

lx@LX:~$ gcc hang.c -o hang
lx@LX:~$ strace ./hang user
……
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xb59000, 4096, PROT_READ)     = 0
munmap(0xb77bf000, 80682)               = 0
getpid()                                = 14539

b.内核态挂死跟踪输出:
lx@LX:~$ strace ./hang system
……
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xddf000, 4096, PROT_READ)     = 0
munmap(0xb7855000, 80682)               = 0
getpid()                                = 14543
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({500, 0},

c. 输出结果分析:

用户态挂死情况下,strace在getpid()一行输出之后没有其他系统调用输出;进程在内核态挂死,最后一行的系统调用nanosleep不能完整显示,这里nanosleep没有返回值表示该调用尚未完成,

因而我们可以得出以下结论:使用strace跟踪挂死程序,如果最后一行系统调用显示完整,程序在逻辑代码处挂死;如果最后一行系统调用显示不完整,程序在该系统调用处挂死。

下面是ltrace 与strace 跟踪我们nginx的情况:
ltrace -r -p 26555(nginx worker 对应的进程号)
  0.000205 epoll_wait(21, 0xf6e550, 512, 500, 0x7fff34eeaa93)                                                                                      = 0
  0.500967 gettimeofday(0x7fff34eeac70, NULL)                                                                                                      = 0
  0.000318 epoll_wait(21, 0xf6e550, 512, 500, 0x7fff34eeaa93)                                                                                      = 0
  0.500945 gettimeofday(0x7fff34eeac70, NULL)                                                                                                      = 0
  0.000243 memcpy(0x6f4fe7, "26", 2)                                                                                                               = 0x6f4fe7
  0.000204 memcpy(0x6f4fee, "2014", 4)                                                                                                             = 0x6f4fee
  0.000255 memcpy(0x6f4ff4, "7", 1)                                                                                                                = 0x6f4ff4
  0.000327 memcpy(0x6f4ff6, "43", 2)                                                                                                               = 0x6f4ff6
  0.000205 memcpy(0x6f4ff9, "11", 2)                                                                                                               = 0x6f4ff9
  0.000200 localtime_r(0x7fff34eeaba8, 0x7fff34eeac30, 0x4bc00a, 12593, 0x7fff34eeaa92)
分析: 0.000205  调用系统所话的时间,单位为微秒,epoll_wait()系统函数,我们可以通过时间来简单的判断一下,运行函数是否异常
strace -r -p 26555(nginx worker 对应的进程号)

     0.000029 recvfrom(46, "POST /rewardapi/v2/applyCancelCo"..., 4096, 0, NULL, NULL) = 453
     0.000105 sendto(9, "*5\r\n$5\r\nHMGET\r\n$21\r\n1111111111:a"..., 88, 0, NULL, 0) = 88
     0.000045 recvfrom(9, 0x408362d0, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
     0.000026 poll([{fd=9, events=POLLIN}], 1, -1) = 1 ([{fd=9, revents=POLLIN}])
     0.000430 recvfrom(9, 0x408362d0, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
     0.000057 poll([{fd=9, events=POLLIN}], 1, -1) = 1 ([{fd=9, revents=POLLIN}])
     0.000426 recvfrom(9, 0x408362d0, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
     0.000062 poll([{fd=9, events=POLLIN}], 1, -1) = 1 ([{fd=9, revents=POLLIN}])
     0.001000 recvfrom(9, 0x408362d0, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
     0.000028 poll([{fd=9, events=POLLIN}], 1, -1) = 1 ([{fd=9, revents=POLLIN}])
     0.000468 recvfrom(9, 0x408362d0, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
     0.000031 poll([{fd=9, events=POLLIN}], 1, -1) = 1 ([{fd=9, revents=POLLIN}])
     0.000893 recvfrom(9, 0x408362d0, 8192, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
     0.000028 poll([{fd=9, events=POLLIN}], 1, -1) = 1 ([{fd=9, revents=POLLIN}])
     0.001047 recvfrom(9, "*3\r\n$40\r\nBB9318B102E320C09B8AB9D"..., 8192, 0, NULL, NULL) = 61
     0.000114 close(37)                 = 0
     0.000025 munmap(0x7fe59c1ba000, 4096) = 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值