type
status
date
slug
summary
tags
category
icon
password
😀
简单介绍一下在linux上追踪系统调用的工具和方法

strace

简介

strace的主要作用:
  1. 系统调用跟踪:记录程序执行期间调用的所有系统调用(如文件操作、进程管理、网络通信等),包括参数和返回值
  1. 信号监控:显示进程接收到的信号(如 SIGSEGVSIGINT
  1. 性能分析:统计系统调用的耗时和调用次数,辅助定位性能瓶颈
下面是使用方式的简单介绍:
常用选项
  • p <PID>:附加到正在运行的进程
  • e trace=<类型>:过滤特定调用(如 filenetworkprocess
  • o <文件>:输出到文件
  • c:统计调用次数和耗时
  • f:跟踪子进程
  • s <长度>:限制输出字符串长度(默认 32,可调大)

示例

例如想知道在 curl www.baidu.com 这个过程中,发生了什么系统调用的时候,可以使用如下指令:
这条指令会追踪在 curl 执行期间发生的系统调用,并将结果输出在 test.txt 这个文件中,下面是文件中的详细内容。
以上仅显示对用户态下的linux系统调用,看不到linux kernel中详细的调用流程,下面进一步介绍一个更加强大的工具。

bpftrace

简介

简单介绍一下bpftrace的核心作用:
  • 动态追踪:无需修改代码或重启服务,实时观测系统行为
  • 低开销:eBPF 在内核中运行,避免传统工具(如 straceperf)的上下文切换开销
  • 脚本化:类似 AWK 的语法,快速编写追踪脚本
  • 多场景支持
    • 内核函数调用追踪
    • 用户空间函数调用追踪(需符号表支持)
    • 系统调用、网络流量、硬件事件等监控
    • 性能分析(延迟、频率统计)
简单一点总结,就是一个脚本化的eBPF应用。

脚本结构

  • 探针类型:指定追踪点(如 kprobeuprobetracepoint
  • 动作:触发时执行的逻辑(打印、统计等)
下面是一些常用的探针
探针
作用
kprobe:函数名
追踪内核函数调用(如 kprobe:do_sys_open
kretprobe:函数名
追踪内核函数返回值
uprobe:二进制:函数
追踪用户空间函数(如 uprobe:/bin/bash:main
tracepoint:子系统:事件
追踪预定义内核事件(如 tracepoint:syscalls:sys_enter_open
interval:s:1
定时触发(每秒 1 次)

示例

这里没有系统性的介绍bpftrace脚本相关的语法和内容,bptrace是一个很强大的工具,具体的使用细节可以参考官方文档
例如此时通过阅读linux源码,可以知道在tcp三次握手阶段,client握手结束后会调用到 tcp_finish_connect()函数,那么可以通过如下脚本来追踪调用到该函数时,函数调用栈的情况。当然也可以结合源码阅读过程中看到的各种函数,使用 kprobe/kretprobe来观察这些函数的调用顺序。
(也可以将脚本单独写成xxx.bt,然后使用bpftrace调用脚本)
最后得到如下输出,可以看到tcp协议栈在这个过程中调用了哪些函数,相比于strace,bpftrace可以从中断一直跟踪到最后。
这里针对文件的解读,可以再深入一些,观察到函数的后面有+1、+435之类的数字,这个是表示该函数在内存中的偏移量,具体来说:
  • 函数基地址 + 偏移量 = 调用点的实际地址例如:tcp_finish_connect+1 表示调用发生在 tcp_finish_connect 函数起始地址向后偏移 1 字节的位置
  • 为什么有偏移量?内核函数编译后会被转换为二进制机器码,+数字 表示调用点距离函数入口的字节偏移,帮助开发者定位到函数内部的具体执行位置
小偏移量(如 +1
  • 通常是函数刚被调用时的返回地址(例如 call 指令后的下一条指令)。
  • 也可能是编译器优化导致的指令对齐(如函数开头填充 nop 指令)。
大偏移量(如 +435
  • 表示调用发生在函数内部的深层次逻辑中。例如 tcp_rcv_state_process+435 说明当前执行点在该函数的第 435 字节处,可能对应某个 if 分支或循环内部。
eBPF map类型简介eBPF入门
Loading...
Patrickhao
Patrickhao
一个新手程序员
Announcement
🎉欢迎来到我的博客🎉
-- 这里会不定期更新 --
👏欢迎随时联系我👏