系统调用追踪工具strace

简介:

当我们想知道某个进程为什么突然卡了,或者是某个工具到底是如何实现的时候。strace就派上了用场。它能将程序的调用信息打印出来。

strace原理:

它的实现基础是ptrace系统调用。ptrace系统调用提供了一种方法来跟踪和控制进程的执行,它可以读取和修改进程地址空间中的内容,包括寄存器的值。ptrace主要用于实现断点调试和跟踪系统调用。

ptrace系统调用

1 #include <sys/ptrace.h>
2 int ptrace(int request, int pid, int addr, int data);

Ptrace 提供了一种父进程可以控制子进程运行,并可以检查和改变它的核心image。它主要用于实现断点调试。

一个被跟踪的进程运行中,在执行系统调用之前,内核会先检查当前进程是否处于被“跟踪”(traced)的状态。如果是的话,内核暂停当前进程并将控制权交给跟踪进程,使跟踪进程得以察看或者修改被跟踪进程的寄存器

在一个进程被跟踪之后,跟踪者进程会在某种意义上充当被跟踪进程的父进程(如使用ps命令就可以看到他们的父子关系),而子进程真正的父进程被保存在其task_struct结构的real_parent成员中。

当子进程产生系统调用时,就会被暂停,父进程会在每次调用wait()时得到子进程停止运行的通知,这时父进程就可以检测和修改子进程了,随后父进程可以让子进程继续运行。当父进程不想跟踪了,可以通过设置PTRACE_KILL标记来终止子进程的运行。也可以通过设置PTRACE_DETACH标记让子进程解除被跟踪,继续正常运行。
函数参数:

  1. request:用于选择一个操作。
  2. pid:目标进程即被跟踪进程的pid。
  3. addr用于修改和拷贝被跟踪进程的进程地址空间的数据。
  4. data功能同addr。

父进程跟踪一个进程的方式有两种:

  1. 调用fork(),然后子进程打上PTRACE_TRACEME标记,并执行exec。
  2. 父进程可以给自己打上PTRACE_ATTACH标记来跟踪一个已有进程。

所以我们看strace有两种用法,一个是strace直接加要运行的程序,一个是用-p指定一个正在运行的进程。

一个进程被跟踪后,他只要接收到一个信号(即使这个信号被设置为忽略)就会停止运行(SIGKILL除外),然后父进程会在每次调用wait()时得到子进程停止运行的通知,这时父进程就可以检测和修改子进程了,随后父进程可以让子进程继续运行。

当父进程不想跟踪了,可以通过设置PTRACE_KILL标记来终止子进程的运行。也可以通过设置PTRACE_DETACH标记让子进程解除被跟踪,继续正常运行。

strace用法:

最简单的用法其实就是trace后面直接跟着要执行的命令。比如:

1 strace ls -l

就能追踪到它的系统调用。

1 execve("/bin/ls", ["ls""-l"], [/* 22 vars */]) = 0
2 brk(0)                                  = 0x2073000
3 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fee98686000
4 access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
5 open("/etc/ld.so.cache", O_RDONLY)      = 3
6 .........

命令参数:

  • -p pid :绑定到一个由pid对应的正在运行的进程。此参数常用来调试后台进程。
  • -e 函数名:只追踪定义函数名。
  • -f :除了跟踪当前进程外,还跟踪其子进程。
  • -o file :将输出信息写到文件file中,而不是显示到标准错误输出(stderr)。

在linux中,很多性能查看命令都是通过读取/proc中的文件实现的。所以我们如果想学习它们的实现,就可以使用strace追踪,用-e筛选出open函数,就知道它读取了什么文件。比如mount命令。

01 strace -eopen mount
02 open("/etc/ld.so.cache", O_RDONLY)      = 3
03 open("/lib64/libblkid.so.1", O_RDONLY)  = 3
04 open("/lib64/libuuid.so.1", O_RDONLY)   = 3
05 open("/lib64/libselinux.so.1", O_RDONLY) = 3
06 open("/lib64/libsepol.so.1", O_RDONLY)  = 3
07 open("/lib64/libc.so.6", O_RDONLY)      = 3
08 open("/lib64/libdl.so.2", O_RDONLY)     = 3
09 open("/proc/filesystems", O_RDONLY)     = 3
10 open("/usr/lib/locale/locale-archive", O_RDONLY) = 3
11 open("/dev/null", O_RDWR)               = 3
12 <span style="color: #ff0000;"><strong>open("/etc/mtab", O_RDONLY)             = 3
13 </strong></span>

参考资料:

http://blog.csdn.net/sealyao/article/details/6710772

转载请注明:旅途@KryptosX » 系统调用追踪工具strace

目录
相关文章
|
2月前
|
Rust 关系型数据库 C语言
使用uftrace跟踪bpf程序的执行
使用uftrace跟踪bpf程序的执行
|
4月前
|
监控 安全 Linux
Linux命令truss详解:系统调用跟踪的利器
`truss`(或`strace`)是Linux调试利器,用于跟踪系统调用和信号。它帮助开发者优化性能、调试错误和进行安全审计。通过附加到进程,记录调用细节、参数、返回值和错误。使用参数如`-d`显示调试信息,`-e`跟踪特定调用,`-o`输出到文件,`-p`跟踪指定进程。注意其对性能的影响,通常需要root权限,并建议过滤输出和结合其他工具分析。
|
存储 网络协议 Linux
高效调试与分析:利用ftrace进行Linux内核追踪(下)
高效调试与分析:利用ftrace进行Linux内核追踪
|
运维 前端开发 关系型数据库
高效调试与分析:利用ftrace进行Linux内核追踪(上)
高效调试与分析:利用ftrace进行Linux内核追踪
|
6月前
|
NoSQL Java 编译器
如何定位strace中系统调用在内核中的位置
要了解内核函数的含义,最好的方法,就是去查询所用内核版本的源代码。
42 0
|
消息中间件 运维 监控
Linux Command strace 调试跟踪(1)
Linux Command strace 调试跟踪(1)
Linux Command strace 调试跟踪(1)
|
缓存 监控 网络协议
Linux Command strace 调试跟踪(2)
Linux Command strace 调试跟踪(2)
Linux Command strace 调试跟踪(2)
|
Linux Shell 网络安全
使用Systemtap跟踪系统调用 (一)
SystemTap是一个诊断Linux系统性能或功能问题的开源软件。它使得对运行时的Linux系统进行诊断调式变得更容易、更简单。有了它,开发者或调试人员不再需要重编译、安装新内核、重启动等烦人的步骤。
654 0
使用Systemtap跟踪系统调用 (一)