Appearance
perf trace —— 系统调用追踪
更新时间:2026-08-06
perf trace 追踪进程的系统调用,显示每次 syscall 的名称、参数、返回值、耗时——回答"程序在跟内核交互什么、有多慢"。
关联:perf-probe.md(内核动态探针)、strace 对比、syscall 原理
一、perf trace 能回答什么问题
| 问题 | 怎么看 |
|---|---|
| 程序做了哪些 syscall? | perf trace ./prog,看输出列表 |
| 哪些 syscall 最耗时? | 关注每个 syscall 后面的耗时(ms) |
| 某个 syscall 的参数/返回值是什么? | 输出中直接显示参数和返回值 |
| 程序是否在某个 syscall 上阻塞? | 看耗时是否远大于正常值 |
| 全系统 syscall 概览? | perf trace -a |
二、基本使用
2.1 追踪命令执行
bash
perf trace ./your_program输出示例:
bash
0.123 ( 0.005 ms): your_prog/12345 openat(dfd: CWD, filename: "/etc/hosts", flags: RDONLY) = 3
0.234 ( 0.003 ms): your_prog/12345 read(fd: 3, buf: 0x7ffe12345678, count: 4096) = 256
0.345 ( 0.001 ms): your_prog/12345 close(fd: 3) = 0
0.456 ( 0.004 ms): your_prog/12345 write(fd: 1, buf: 0x7ffe12345678, count: 256) = 256
0.567 (10.234 ms): your_prog/12345 nanosleep(rqtp: 0x7ffe12345680, ...) = 0| 列 | 含义 |
|---|---|
| 时间戳 | syscall 开始时间(相对于起始时间) |
| (耗时) | syscall 执行的 wall-clock 时间(毫秒) |
| 进程/线程 | 进程名/PID |
| syscall 名 | 系统调用名称 |
| 参数 | 解析后的参数值 |
| = 返回值 | 系统调用返回值 |
2.2 追踪运行中的进程
bash
perf trace -p <pid>2.3 全系统追踪
bash
# 全系统,持续 10 秒
perf trace -a -- sleep 10三、常用选项
| 选项 | 含义 | 示例 |
|---|---|---|
-e <syscall> | 只追踪指定 syscall | -e open,read,write |
--exclude <syscall> | 排除某些 syscall | --exclude clock_gettime,nanosleep |
-s | 按耗时汇总排序 | 看哪些 syscall 花时间最多 |
-S | 按调用次数汇总排序 | 看哪些 syscall 调用最频繁 |
-T | 显示每个 syscall 耗时(默认) | — |
-o <file> | 输出到文件 | -o trace.txt |
-G <group> | 按 cgroup 过滤 | — |
--call-graph | 记录调用栈(需 dwarf) | --call-graph dwarf |
四、汇总模式(-s / -S)
按耗时汇总
bash
perf trace -s ./your_programbash
Summary of events:
your_prog (12345), 2345 events, 99.5%, 1234.567 ms
syscall calls total avg min max
(ms) (ms) (ms) (ms)
--------------- -------- --------- --------- --------- ---------
nanosleep 10 10000.000 1000.000 100.000 1000.000
write 2000 234.567 0.117 0.001 5.678
read 2000 123.456 0.062 0.001 3.456
openat 10 1.234 0.123 0.089 0.234
close 10 0.567 0.057 0.012 0.123快速判断:
nanosleep总耗时 10 秒但 avg 1 秒——程序在 sleep,不是真的在干活。write2000 次 max 5.678 ms——某次写操作异常慢。
按调用次数汇总
bash
perf trace -S ./your_program按调用次数降序,方便发现"频繁但轻量的 syscall"(如 futex、clock_gettime)。
五、perf trace vs strace
| perf trace | strace | |
|---|---|---|
| 原理 | 内核 tracepoint / BPF | ptrace |
| 开销 | 极低(< 1%) | 较高(可能 10-50%) |
| 参数解析 | 智能解析(FD 路径、flag 含义) | 需要 -v 或手动解析 |
| 耗时信息 | 自动显示 | 需要 -T |
| 过滤精度 | 支持按 cgroup/CPU 过滤 | 仅按 PID/syscall |
| 对程序影响 | 几乎无影响 | 会影响程序执行时序 |
| 可用性 | 需 Linux 4.1+ | 几乎所有 Linux |
推荐:能用
perf trace就用它,开销远小于strace。strace保留给极老的系统或需要ptrace特殊能力的场景。
六、实战场景
场景 1:程序响应慢,怀疑在 sleep
bash
perf trace -s ./your_program如果 nanosleep/clock_nanosleep/select/poll/epoll_wait 总耗时占大头→程序在等。
场景 2:定位 syscall 异常延迟
bash
perf trace -e read,write,openat,close -T ./your_program如果某次 write 耗时 > 10ms(SSD 正常 < 0.1ms),说明 I/O 路径有问题(磁盘慢、文件系统锁、page cache 等)。
场景 3:判断程序是否做了不必要的 syscall
bash
perf trace -S ./your_program如果看到大量 clock_gettime(每秒几千次)或 sched_yield,说明程序可能在 busy-loop 或自旋等待——不应该出现。
场景 4:追踪网络 IO
bash
perf trace -e sendto,recvfrom,sendmsg,recvmsg,accept,connect -p <pid>实时看到每次网络 IO 的大小和延迟。
七、注意事项
- 权限:通常需要 root 或
CAP_PERFMON。perf_event_paranoid≤ 1 时可用。 - 输出量大:
perf trace -a全系统输出可能瞬间几万行。先用-s看汇总。 - 参数解析:不是所有 syscall 的参数都能自动解析为人类可读的形式。
- 时序影响:虽然开销远低于 strace,但追踪本身会引入微小的时序偏差。
八、与相关文档的交叉引用
| 场景 | 文档 |
|---|---|
| 深入内核函数追踪 | perf-probe.md |
| 追踪上下文切换 | perf-sched.md |
| 多线程+IO 程序分析 | perf-multithread-io-analysis.md |
| syscall 原理 | syscall 详解 |
九、一句话总结
perf trace是程序与内核交互的"透明玻璃"——用极低开销实时追踪每次系统调用及其耗时,一眼看出程序是在"干活"还是"在等",是定位 IO/sleep 类延迟问题的第一工具。