1. strace 入门:系统调用的“X 光机”
strace 是 Linux 系统调试工具箱中最基础、最常用的工具之一。它能够拦截并记录进程发起的每一次系统调用(System Call)以及接收到的信号。对于内核开发者、系统管理员和性能调优工程师而言,strace 就像一台“X 光机”,让你清晰地看到用户态程序与内核态之间的每一次交互。
1.1 strace 是什么
strace 的全称是 System Trace,它是一个用户态的跟踪工具,利用 Linux 内核的 ptrace 系统调用来监控目标进程。当目标进程执行系统调用时,strace 会捕获该调用的名称、参数、返回值以及执行耗时。
| 特性 | 说明 |
|---|---|
| 拦截对象 | 系统调用(如 open, read, write, ioctl)和信号 |
| 工作模式 | 跟踪已运行进程(-p)或启动新进程 |
| 输出内容 | 调用名、参数、返回值、错误码、耗时(-T) |
| 过滤能力 | 按系统调用类型(-e trace=file)、进程(-p)过滤 |
| 依赖内核机制 | ptrace 系统调用 |
1.2 strace 的工作原理
strace 的核心机制建立在 Linux 的 ptrace 系统调用之上。当 strace 通过 ptrace(PTRACE_TRACEME, ...) 或 ptrace(PTRACE_ATTACH, ...) 附加到目标进程后,内核会将目标进程发出的所有系统调用事件通知给 strace。strace 在每次系统调用入口和返回处暂停目标进程,读取寄存器中的参数和返回值,然后恢复目标进程的执行。
1.3 strace 的安装
strace 是 Linux 发行版的标准工具,几乎所有的包管理器都内置了它。以下是主流发行版的安装命令:
| 发行版 | 包管理器 | 安装命令 |
|---|---|---|
| Debian / Ubuntu | apt | sudo apt install strace |
| RHEL / CentOS / Fedora | yum / dnf | sudo yum install strace 或 sudo dnf install strace |
| Arch Linux | pacman | sudo pacman -S strace |
| Alpine Linux | apk | sudo apk add strace |
安装完成后,可以通过以下命令验证版本:
strace --version
输出示例:
strace -- version 5.19
Copyright (C) 1991-2022 The strace developers.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1.4 strace 的基本用法
strace 的使用模式非常直观,主要分为两种:启动并跟踪新进程 和 附加到已运行的进程。
1.4.1 跟踪一个新启动的命令
这是最常用的模式。直接在 strace 后面跟上要执行的命令即可:
strace ls -l /tmp
执行后,strace 会输出 ls 命令执行过程中发起的每一次系统调用。输出内容通常非常庞大,因为一个简单的 ls 命令也会触发数十次系统调用。
1.4.2 附加到已运行的进程
使用 -p 参数可以附加到一个正在运行的进程(需要相应权限):
strace -p 1234
其中 1234 是目标进程的 PID。附加后,strace 会实时输出该进程后续的系统调用。按 Ctrl+C 可以分离跟踪。
1.4.3 常用选项速查
| 选项 | 作用 | 示例 |
|---|---|---|
-o file |
将输出写入文件,而非标准错误 | strace -o trace.log ls |
-e trace=set |
只跟踪指定的系统调用集合 | strace -e trace=open,read ls |
-e trace=file |
只跟踪与文件操作相关的系统调用 | strace -e trace=file ls |
-e trace=network |
只跟踪与网络相关的系统调用 | strace -e trace=network curl http://example.com |
-c |
统计模式:汇总系统调用的次数、耗时和错误数 | strace -c ls |
-T |
显示每次系统调用的耗时(微秒级) | strace -T ls |
-f |
跟踪由目标进程创建的子进程(fork) | strace -f -o trace.log ./server |
-p PID |
附加到指定 PID 的进程 | strace -p 1234 |
1.4.4 第一个实战示例:跟踪 ls 命令
执行以下命令,观察 ls 如何读取目录内容:
strace -e trace=open,openat,read,write,close ls /tmp
输出片段示例:
openat(AT_FDCWD, "/tmp", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
getdents64(3, 0x7ffc8a3b2000, 32768) = 48
getdents64(3, 0x7ffc8a3b2000, 32768) = 0
close(3) = 0
write(1, "file1.txt file2.txt\n", 21) = 21
openat:打开 /tmp 目录,返回文件描述符 3。getdents64:读取目录条目,第一次返回 48 字节数据,第二次返回 0 表示读取完毕。close:关闭目录文件描述符。write:将格式化后的文件名列表写入标准输出(文件描述符 1)。
1.4.5 统计模式:快速定位性能热点
使用 -c 选项可以快速了解程序在哪些系统调用上花费了最多时间:
strace -c find /usr -name "*.conf"
输出示例:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
45.23 0.123456 2.345 52635 newfstatat
30.12 0.082134 1.567 52389 getdents64
15.67 0.042789 0.987 43321 openat
5.34 0.014567 0.345 42210 close
3.64 0.009876 0.234 42100 read
------ ----------- ----------- --------- --------- ----------------
100.00 0.272822 232655 total
newfstatat 占 45%),说明程序可能频繁进行文件状态查询,可以考虑使用缓存或减少文件扫描次数来优化。
1.5 本章小结
- strace 是基于
ptrace的系统调用跟踪工具,用于观察用户态程序与内核的交互。 - 安装简单,所有主流 Linux 发行版均可通过包管理器一键安装。
- 基本用法包括
strace <command>(跟踪新进程)和strace -p <PID>(附加到运行进程)。 - 常用选项
-e trace=、-o、-c、-T、-f提供了强大的过滤和统计能力。 - strace 会引入性能开销,生产环境使用时建议配合
-e过滤或-c统计模式,避免全量跟踪。