mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
4356 字
12 分钟
追踪与可观测性
2024-07-28

第 17 章中,我们学习了如何通过内核模块扩展内核功能,也提到了 printk 这个最朴素的调试手段。但 printk 有一个致命的局限——它只能输出你预先编码的信息。当生产环境出现偶发性延迟、吞吐量骤降或死锁时,你不可能提前在每一行可疑代码里插入 printk,更不可能为了加一条日志而重新编译和加载内核模块。

你需要的是一种无需修改内核源码、开销极低、能在线上实时运行的观测能力。这就是 Linux 内核追踪与可观测性(Tracing & Observability) 体系要解决的核心问题。

本章将从可观测性的演进历史出发,依次深入 ftrace、perf、eBPF 三大核心工具,最后介绍 bpftrace 和 BCC 这两个让 eBPF 真正走向生产的高层接口。

一、可观测性的演进:从 printk 到 eBPF#

Linux 内核的可观测性工具经历了一条清晰的演进路径——从最原始的日志输出,到静态追踪点,再到完全可编程的动态追踪框架:

graph LR A["printk<br/>日志输出"] --> B["ftrace<br/>函数追踪"] B --> C["perf<br/>性能计数"] C --> D["eBPF<br/>可编程追踪"] style A fill:#f9f,stroke:#333 style B fill:#bbf,stroke:#333 style C fill:#bfb,stroke:#333 style D fill:#fbb,stroke:#333
阶段工具能力开销可编程性
日志输出printk输出预定义信息高(I/O 锁竞争)
函数追踪ftrace追踪函数调用/返回中(动态插桩)有限
性能计数perf采样 + 硬件计数器低(采样率可调)有限
可编程追踪eBPF在内核安全执行自定义逻辑极低(JIT 编译)完全
Note

这四个阶段并非替代关系,而是互补关系printk 仍然是开发阶段的首选调试手段;ftrace 在函数级追踪上无可替代;perf 是性能剖析的瑞士军刀;eBPF 则将可观测性推向了可编程的新高度。生产环境中,它们往往配合使用。

二、ftrace:内核函数追踪器#

ftrace 是 Linux 内核内置的追踪框架,名字源自”function tracer”,但其能力远不止函数追踪——它还支持事件追踪、函数图形化追踪、延迟追踪等多种模式。ftrace 的所有功能通过 debugfs(通常挂载在 /sys/kernel/debug/tracing)暴露给用户空间。

2.1 动态插桩机制:-pg、mcount 与 fentry#

ftrace 的核心问题是:如何在不修改内核源码的情况下,在任意函数入口插入追踪代码?答案依赖于编译器的配合和运行时的动态修补:

传统方式(x86 32 位 / 早期内核)

  1. 编译内核时,GCC 的 -pg 选项在每个函数入口插入一条 call mcount 指令
  2. 默认情况下,mcount 是一个空函数,直接返回——几乎零开销
  3. 启用追踪时,ftrace 将 mcount 处的 call 指令动态替换为 call ftrace_caller
  4. ftrace_caller 保存上下文后调用用户注册的追踪回调函数

现代方式(x86_64 / GCC 5.0+ / Clang)

  1. 编译器在每个函数入口插入 call __fentry__(GCC)或 call __cyg_profile_func_enter(Clang)
  2. 内核使用 ftrace_patch_location 结构记录每个插桩点的位置
  3. 启用追踪时,通过 text_poke 机制将 call __fentry__ 替换为跳转到追踪处理器的指令

关键源码位于:

  • kernel/trace/ftrace.c — ftrace 核心逻辑
  • include/linux/ftrace.h — ftrace 接口定义
  • arch/x86/kernel/ftrace.c — x86 架构相关的动态插桩实现
Warning

ftrace 的动态插桩直接修改内核代码段(.text),这要求内核映射为可写。出于安全考虑,现代内核使用 text_poke 机制临时映射一个可写页面来完成修补,修补完成后立即恢复为只读——这是第 14 章中内存屏障和 set_memory_rw/set_memory_ro 的实际应用。

2.2 function 追踪器#

最基础的追踪模式,记录每个被调用函数的入口:

# 查看可用的追踪器
cat /sys/kernel/debug/tracing/available_tracers
# function function_graph wakeup wakeup_rt wakeup_dl irqsoff preemptoff
# preemptirqsoff blk mmiotrace branch nop
# 启用 function 追踪器
echo function > /sys/kernel/debug/tracing/current_tracer
# 只追踪 schedule 相关函数
echo 'fn:schedule*' > /sys/kernel/debug/tracing/set_ftrace_filter
# 查看追踪结果
cat /sys/kernel/debug/tracing/trace
# <...>-1234 [000] d... 100.000: schedule <-schedule_timeout
# <...>-1234 [000] d... 100.001: schedule <-do_nanosleep

2.3 function_graph 追踪器#

function_graph 不仅记录函数入口,还记录函数返回,从而展示完整的调用栈和执行时间:

echo function_graph > /sys/kernel/debug/tracing/current_tracer
echo '*schedule*' > /sys/kernel/debug/tracing/set_graph_function
cat /sys/kernel/debug/tracing/trace
# 0) | schedule() {
# 0) | __schedule() {
# 0) 0.123 us | rcu_note_context_switch();
# 0) 1.456 us | }
# 0) 1.789 us | }

输出中的时间戳表示函数的执行耗时——这是定位性能热点的利器。

2.4 Trace Events 与 trace-cmd#

除了函数追踪,ftrace 还支持静态追踪点(Tracepoint)——内核开发者在关键路径预先埋设的追踪点,位于 include/trace/events/ 目录下。每个 Tracepoint 定义了可追踪的事件名称和字段:

# 列出所有可用的追踪事件
ls /sys/kernel/debug/tracing/events/
# block bpf cgroup cpuhp exceptions filemap fs irq jbd2
# kvm lock module net nmi oom power printk random
# ras raw_syscalls rcu regulator rpm sched signal skb
# sock sunrpc swiotlb syscalls task timer vmscan workqueue writeback
# 启用调度事件追踪
echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable

trace-cmd 是 ftrace 的前端工具,大幅简化了操作流程:

# 安装 trace-cmd
sudo apt install trace-cmd
# 追踪 sched_switch 事件 5 秒
trace-cmd record -e sched:sched_switch -p function_graph sleep 5
# 查看报告
trace-cmd report

三、perf:性能计数器分析#

如果说 ftrace 关注的是”内核执行了什么路径”,那么 perf 关注的是”这些路径执行得有多快、为什么慢”。perf 的全称是 Performance Events,它利用 CPU 的 PMU(Performance Monitoring Unit)硬件计数器和内核的软件事件,提供采样分析和精确计数两种模式。

3.1 硬件事件与软件事件#

perf 能观测的事件分为两大类:

硬件事件(来自 CPU PMU):

事件含义典型用途
cyclesCPU 周期数计算指令吞吐量
instructions已执行指令数计算 CPI(Cycles Per Instruction)
cache-references缓存引用次数评估缓存压力
cache-misses缓存未命中次数计算缓存命中率
branch-misses分支预测失败次数评估分支预测效率
stalled-cycles-frontend前端停顿周期指令获取瓶颈
stalled-cycles-backend后端停顿周期执行单元瓶颈

软件事件(来自内核统计):

事件含义
cpu-clockCPU 时钟任务
task-clock任务时钟
page-faults缺页异常
context-switches上下文切换
cpu-migrationsCPU 迁移
minor-faults次缺页
major-faults主缺页

3.2 perf stat:计数模式#

perf stat 统计指定事件的总计数,适合宏观性能评估:

# 统计命令的所有默认事件
perf stat ./my_program
# 统计缓存命中率
perf stat -e cache-references,cache-misses ./my_program
# 1,234,567 cache-references
# 45,678 cache-misses # 3.70% of all cache refs
# 统计整个系统的上下文切换
perf stat -e context-switches -a sleep 5

缓存命中率是评估程序数据局部性的关键指标:

缓存命中率=1cache-missescache-references\text{缓存命中率} = 1 - \frac{\text{cache-misses}}{\text{cache-references}}

命中率低于 90% 通常意味着存在严重的缓存问题,需要优化数据结构布局或访问模式。

3.3 perf record + report:采样模式#

perf record 基于采样(Sampling)原理工作:每隔 N 个事件(由采样频率控制),记录一次当前 CPU 上正在执行的指令地址和调用栈:

# 以 99Hz 频率采样 CPU 性能数据
perf record -F 99 -g -- ./my_program
# 对整个系统采样 10 秒
perf record -F 99 -ag -- sleep 10
# 分析采样数据
perf report

perf report 会展示一个按采样占比排序的函数列表,配合 -g 参数还能展示完整的调用图(Call Graph),帮你快速定位热点函数。

3.4 perf top:实时热点#

perf top 类似 top 命令,但显示的是函数级别的 CPU 热点,而非进程级别:

# 实时显示内核和用户态函数热点
sudo perf top
# 只看内核态热点
sudo perf top -k /path/to/vmlinux
# 指定事件
sudo perf top -e cache-misses

3.5 perf annotate:指令级分析#

perf report 定位到热点函数后,perf annotate 可以进一步展示指令级别的采样分布:

perf annotate hot_function

输出中,每条汇编指令旁边会标注采样命中的百分比——百分比最高的指令就是瓶颈所在。这在优化循环、分支和内存访问模式时极为有用。

perf 的核心源码位于 kernel/events/ 目录,其中 kernel/events/core.c 实现了 perf 事件的核心框架,kernel/events/ring_buffer.c 实现了用户空间与内核之间的环形缓冲区。

四、eBPF:革命性的可编程可观测性#

eBPF(extended Berkeley Packet Filter)是 Linux 内核近年来最重要的创新之一。它从一个简单的网络包过滤器,演变成了一个通用的内核可编程框架——你可以在不修改内核源码、不加载内核模块的情况下,安全地在内核中运行自定义逻辑。

4.1 从 BPF 到 eBPF:演进之路#

1992 年,Steven McCanne 和 Van Jacobson 提出经典 BPF(cBPF),用于 tcpdump 等网络抓包工具的高效包过滤。cBPF 的设计简洁而优雅:一个基于寄存器的虚拟机,指令集固定,只用于过滤网络包。

2014 年,Alexei Starovoitov 在 Linux 3.18 中引入 eBPF,将 BPF 推向了全新的维度:

  • 寄存器从 2 个 32 位扩展到 10 个 64 位
  • 指令集大幅扩展,支持函数调用、原子操作等
  • 引入 BPF Map,实现内核与用户空间的数据共享
  • 引入 BPF 验证器,确保程序的安全性
  • 支持挂载到 kprobe、tracepoint、XDP 等多种钩子点
  • 5.2+ 内核支持 BTF(BPF Type Format),实现内核数据结构的类型信息传递
graph TB subgraph 用户空间 TOOL["用户工具<br/>bpftrace / BCC / libbpf"] MAP_R["BPF Map 读取<br/>用户空间消费数据"] end subgraph 内核空间 VERIFIER["BPF 验证器<br/>安全检查"] JIT["JIT 编译器<br/>BPF→本机指令"] PROG["eBPF 程序执行<br/>kprobe/tracepoint/XDP/..."] MAP_W["BPF Map 写入<br/>内核侧存储数据"] end subgraph 钩子点 KP["kprobe / kretprobe"] TP["tracepoint"] XDP["XDP<br/>网络驱动层"] TC["tc<br/>流量控制"] CG["cgroup"] end TOOL -->|"1. 加载 BPF 程序"| VERIFIER VERIFIER -->|"2. 验证通过"| JIT JIT -->|"3. 编译为本机码"| PROG KP --> PROG TP --> PROG XDP --> PROG TC --> PROG CG --> PROG PROG -->|"4. 写入数据"| MAP_W MAP_W -.->|"5. 共享内存"| MAP_R style VERIFIER fill:#fbb,stroke:#333 style JIT fill:#bfb,stroke:#333 style PROG fill:#bbf,stroke:#333 style MAP_W fill:#fbf,stroke:#333

4.2 eBPF 程序类型#

eBPF 程序不是”一段通用代码”,而是针对特定钩子点类型编写的专用程序。内核定义了数十种程序类型(enum bpf_prog_type),每种类型决定了程序可以挂载的位置、可以调用的辅助函数、可以访问的上下文数据:

程序类型钩子点典型用途
BPF_PROG_TYPE_KPROBE内核函数入口/返回追踪内核函数行为
BPF_PROG_TYPE_TRACEPOINT静态追踪点低开销事件追踪
BPF_PROG_TYPE_PERF_EVENTperf 事件性能计数器驱动的采样
BPF_PROG_TYPE_XDP网络驱动收包路径DDoS 防御、负载均衡
BPF_PROG_TYPE_SCHED_CLStc 流量控制网络流量分类与标记
BPF_PROG_TYPE_CGROUP_SKBcgroup 网络钩子容器网络策略
BPF_PROG_TYPE_SOCKET_FILTER套接字消息过滤网络包过滤
BPF_PROG_TYPE_LSMLinux 安全模块安全策略执行

程序类型的定义位于 include/uapi/linux/bpf.h,每种类型的上下文结构和可用辅助函数在 kernel/bpf/ 和各子系统中实现。

4.3 BPF Map:内核与用户空间的数据桥梁#

eBPF 程序运行在内核中,但它产生的数据需要传递给用户空间进行展示和持久化;反过来,用户空间也需要向内核传递配置参数。BPF Map 就是这座桥梁——一种内核与用户空间共享的键值存储。

BPF Map 支持多种数据结构类型:

Map 类型数据结构典型用途
BPF_MAP_TYPE_HASH哈希表通用键值存储、统计计数
BPF_MAP_TYPE_ARRAY数组索引式存储、配置传递
BPF_MAP_TYPE_PERCPU_HASH每 CPU 哈希表高性能统计(无锁)
BPF_MAP_TYPE_PERF_EVENT_ARRAYperf 事件数组向用户空间发送事件
BPF_MAP_TYPE_RINGBUF环形缓冲区高效事件流传输
BPF_MAP_TYPE_STACK_TRACE调用栈存储火焰图数据采集
BPF_MAP_TYPE_LRU_HASHLRU 哈希表有限容量的缓存

在 eBPF 程序中,通过 bpf_map_lookup_elem()bpf_map_update_elem() 等辅助函数操作 Map;在用户空间,通过 bpf() 系统调用的 BPF_MAP_LOOKUP_ELEMBPF_MAP_UPDATE_ELEM 等命令读写 Map。

Note

BPF_MAP_TYPE_PERCPU_HASH 是高性能场景的首选——每个 CPU 拥有独立的哈希表副本,eBPF 程序写入时无需加锁,用户空间读取时再合并各 CPU 的数据。这利用了第 14 章中 per-CPU 变量的思想:通过空间换时间,消除锁竞争。

4.4 BPF 验证器:安全的基石#

eBPF 允许普通用户向内核注入代码——这在安全上是极度危险的。BPF 验证器(Verifier)是 eBPF 安全模型的基石,它在程序加载时进行静态分析,确保程序不会危害内核的稳定性:

验证器的核心检查包括:

  1. DAG 检查:程序必须是无环的有向无环图(DAG),不允许循环——确保程序必定终止
  2. 指令数上限:早期限制为 4096 条指令,5.2+ 内核通过 bpf2bpf 调用链支持最多 8 层嵌套函数调用,总指令数上限为 100 万条
  3. 寄存器状态追踪:验证器模拟执行程序,追踪每个寄存器可能的值范围(scalar range)和类型(指针、Map 值、上下文等),确保不会发生越界访问
  4. 空指针检查:所有指针解引用前必须经过 NULL 检查
  5. 越界访问检查:所有内存访问必须在已验证的范围内
  6. 辅助函数权限:不同程序类型只能调用特定的辅助函数子集

验证器的源码位于 kernel/bpf/verifier.c——这是内核中最复杂的代码之一,超过 20000 行,实现了基于抽象解释(Abstract Interpretation)的数据流分析。

Warning

验证器的错误信息有时晦涩难懂。当你的 eBPF 程序被拒绝时,可以通过 llvm-objdump -S 查看生成的 BPF 字节码,结合验证器的日志逐条对照。BCC 和 bpftrace 会自动处理大部分验证器兼容性问题。

五、bpftrace:一行命令的追踪魔法#

bpftrace 是 eBPF 的高级前端,提供了一种类似 awk 的一行命令接口,让你无需编写 C 代码就能利用 eBPF 的全部能力。它的设计哲学是:一行命令胜过千行代码

5.1 基本语法#

bpftrace 的核心语法模板:

探针类型:探针标识 /过滤条件/ { 动作 }

常用探针类型:

探针含义示例
kprobe:func内核函数入口kprobe:vfs_read
kretprobe:func内核函数返回kretprobe:vfs_read
tracepoint:category:event静态追踪点tracepoint:sched:sched_switch
uprobe:binary:func用户函数入口uprobe:/bin/bash:readline
uretprobe:binary:func用户函数返回uretprobe:/bin/bash:readline
profile:hz:freq定时采样profile:hz:99
interval:s:sec定时输出interval:s:1

5.2 实用一行命令#

# 追踪所有 openat 系统调用,打印进程名和文件路径
bpftrace -e 'kprobe:__x64_sys_openat { printf("%s -> %s\n", comm, str(arg2)) }'
# 统计每个进程的 vfs_read 调用次数
bpftrace -e 'kprobe:vfs_read { @reads[comm] = count() }'
# 追踪 vfs_read 的返回值分布(直方图,单位微秒)
bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs }
kretprobe:vfs_read /@start[tid]/ {
@us[comm] = hist((nsecs - @start[tid]) / 1000);
delete(@start[tid])
}'
# 追踪新进程创建
bpftrace -e 'tracepoint:sched:sched_process_exec { printf("%s -> %s\n", comm, str(args->filename)) }'
# 每秒输出一次系统调用计数
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @syscalls[comm] = count() }
interval:s:1 { print(@syscalls); clear(@syscalls) }'

bpftrace 内部将一行命令编译为 eBPF 字节码,通过 bpf() 系统调用加载到内核,然后从 perf 缓冲区读取输出——整个过程对用户完全透明。

六、BCC 工具集:生产可观测性的瑞士军刀#

BCC(BPF Compiler Collection)是 iovisor 项目开发的一套 eBPF 工具集,提供了数十个预制的可观测性工具,覆盖 CPU、内存、文件 I/O、网络、安全等各个维度。BCC 使用 Python/Lua 作为前端,C 作为 eBPF 程序后端,运行时动态编译和加载 eBPF 程序。

6.1 核心工具一览#

工具功能典型场景
execsnoop追踪新进程执行安全审计、排查神秘进程
opensnoop追踪文件打开操作排查配置文件读取问题
biolatency块设备 I/O 延迟直方图评估存储性能
biosnoop追踪每次块 I/O 的延迟定位慢 I/O
bitesize进程级 I/O 大小分布分析 I/O 模式
cpudistCPU on/off 时间分布评估 CPU 利用率
offcputime离 CPU 时间追踪定位线程阻塞原因
slabratetopSlab 分配速率排行内存分配热点
tcpconnect追踪 TCP 主动连接网络连接审计
tcpaccept追踪 TCP 被动接受服务端连接监控
tcplifeTCP 连接生命周期连接时长统计
tcpretransTCP 重传事件网络质量评估
memleak内存泄漏检测长期运行服务内存增长
deadlock死锁检测排查锁竞争问题
stackcount调用栈计数火焰图数据采集

6.2 典型使用场景#

场景一:排查偶发性延迟

# 追踪块设备 I/O 延迟分布
sudo biolatency -m
# msecs : count distribution
# 0 -> 1 : 1234 |********************|
# 1 -> 2 : 56 |* |
# 2 -> 4 : 12 | |
# 64 -> 128 : 3 | | ← 异常长尾!

如果发现 64ms~128ms 的长尾延迟,可以进一步用 biosnoop 定位具体的 I/O 请求:

sudo biosnoop
# TIME(s) COMM PID DISK T SECTOR BYTES LAT(ms)
# 1.234 mysqld 1234 sda R 12345678 8192 0.234
# 1.567 mysqld 1234 sda W 23456789 4096 67.890 ← 异常!

场景二:安全审计——追踪新进程

sudo execsnoop
# PCOMM PID PPID RET ARGS
# bash 12345 12300 0 /bin/bash
# curl 12346 12345 0 /usr/bin/curl http://suspicious.com

场景三:内存泄漏检测

# 追踪指定进程的内存分配/释放不匹配
sudo memleak -p 1234
# Attaching to pid 1234, Ctrl+C to quit.
# ============================================
# Stack Traces with Unfreed Allocations:
# ============================================
# 4096 bytes in 1 allocations from stack
# alloc_handler+0x23 [my_server]
# process_request+0x45 [my_server]
# main_loop+0x12 [my_server]

七、ftrace、perf 与 eBPF 的协作#

三大工具各有侧重,在实际排查中往往需要组合使用:

  1. 先用 perf top 定位热点函数——快速缩小范围
  2. 再用 ftrace function_graph 分析调用路径——理解执行流
  3. 最后用 eBPF 精确度量——在热点路径上插入计数器、直方图、延迟追踪
# 第一步:perf 定位热点
sudo perf top -g
# 第二步:ftrace 分析调用路径
sudo trace-cmd record -p function_graph -l hot_function sleep 5
sudo trace-cmd report
# 第三步:eBPF 精确度量
sudo bpftrace -e 'kprobe:hot_function { @start[tid] = nsecs }
kretprobe:hot_function /@start[tid]/ {
@latency = hist((nsecs - @start[tid]) / 1000);
delete(@start[tid])
}'

八、动手实践#

实践一:使用 trace-cmd 追踪内核函数#

# 安装工具
sudo apt install trace-cmd
# 追踪 schedule 函数的调用图,持续 3 秒
sudo trace-cmd record -p function_graph -l schedule sleep 3
sudo trace-cmd report | head -50
# 追踪 sched_switch 事件
sudo trace-cmd record -e sched:sched_switch sleep 5
sudo trace-cmd report

实践二:使用 perf 分析缓存性能#

# 安装工具
sudo apt install linux-tools-common linux-tools-$(uname -r)
# 查看缓存命中率
perf stat -e cache-references,cache-misses,L1-dcache-loads,L1-dcache-load-misses \
dd if=/dev/zero bs=1M count=1024 | md5sum
# 采样并生成火焰图(需要 FlameGraph 工具)
perf record -F 99 -ag -- sleep 10
perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg
# 实时查看内核热点
sudo perf top -k /boot/vmlinux-$(uname -r)

实践三:使用 bpftrace 追踪内核函数#

# 安装 bpftrace
sudo apt install bpftrace
# 追踪 openat 系统调用
sudo bpftrace -e 'kprobe:__x64_sys_openat { printf("PID=%d COMM=%s FILE=%s\n", pid, comm, str(arg2)) }'
# 统计每个进程的 vfs_read 调用次数
sudo bpftrace -e 'kprobe:vfs_read { @reads[comm] = count() }' -c 'sleep 5'
# 追踪 TCP 连接建立
sudo bpftrace -e 'kprobe:tcp_v4_connect { printf("%s -> %s\n", comm, ntop(arg2)) }'

实践四:使用 BCC 工具集#

# 安装 BCC
sudo apt install bpfcc-tools linux-headers-$(uname -r)
# 追踪新进程
sudo execsnoop-bpfcc
# 块设备 I/O 延迟直方图
sudo biolatency-bpfcc -m
# 追踪 TCP 重传
sudo tcpretrans-bpfcc
# 内存泄漏检测
sudo memleak-bpfcc -p $(pgrep my_server)
Note

BCC 工具在 Ubuntu/Debian 上的命令名带有 -bpfcc 后缀(如 execsnoop-bpfcc),在 RHEL/CentOS 上则没有后缀(如 execsnoop)。这是因为 BCC 工具与系统自带的旧版本同名,需要通过后缀区分。

实践五:对比 ftrace 与 eBPF 的开销#

# 使用 ftrace 追踪 schedule 函数,测量开销
echo nop > /sys/kernel/debug/tracing/current_tracer
echo 0 > /sys/kernel/debug/tracing/tracing_on
# 基准测试
perf stat -e cycles,instructions -- dd if=/dev/zero bs=1M count=512 of=/dev/null 2>&1 | tee baseline.txt
# 启用 ftrace
echo function > /sys/kernel/debug/tracing/current_tracer
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 同样的测试
perf stat -e cycles,instructions -- dd if=/dev/zero bs=1M count=512 of=/dev/null 2>&1 | tee ftrace.txt
# 对比 cycles 差异
# 关闭追踪
echo nop > /sys/kernel/debug/tracing/current_tracer

参考资料#

内核源码#

路径内容
kernel/trace/ftrace 核心实现(ftrace.c、trace.c、trace_events.c)
kernel/events/perf 事件框架(core.c、ring_buffer.c、internal.h)
kernel/bpf/eBPF 核心(verifier.c、syscall.c、core.c、map_iter.c)
include/linux/ftrace.hftrace 接口与数据结构定义
include/uapi/linux/bpf.heBPF 用户态 API(程序类型、Map 类型、辅助函数)
include/trace/events/内核静态追踪点定义
arch/x86/kernel/ftrace.cx86 架构 ftrace 动态插桩实现

官方文档#

手册页#

  • man 1 perf — perf 工具手册
  • man 1 perf-stat — perf stat 子命令
  • man 1 perf-record — perf record 子命令
  • man 8 bpftrace — bpftrace 参考手册

书籍#

书籍作者侧重
《Systems Performance》Brendan Gregg性能分析与可观测性的百科全书
《BPF Performance Tools》Brendan GreggeBPF 性能工具的权威指南
《Linux Observability with BPF》David Calavera 等eBPF 可观测性实践
《Learning eBPF》Liz RiceeBPF 入门与实战

在线资源#


printk 到 ftrace,从 perf 到 eBPF,Linux 内核的可观测性体系走过了一条从”看日志”到”可编程观测”的演进之路。ftrace 能追踪内核的每一步执行,perf 能精确度量性能瓶颈,eBPF 则将两者统一在一个安全、高效、可编程的框架之下。而 bpftrace 和 BCC 让 eBPF 的能力触手可及——一行命令就能洞察内核的内部运作。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

追踪与可观测性
https://blog.souloss.com/posts/linux-internals/tracing-and-observability/
作者
Souloss
发布于
2024-07-28
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

相关文章 智能推荐
1
系列导读
eBPF 本系列从 eBPF 的底层原理出发,系统讲解 eBPF 虚拟机、验证器、Map 数据结构、Hook 机制、CO-RE 可移植性,再到 XDP/TC 网络处理、LSM 安全、Cilium 实践、Wasm 融合、Kubernetes 集成与生产部署,带你从「听说过 eBPF」进阶到「能用 eBPF 解决真实问题」。
2
综合实战
Linux内核 综合运用前 19 章知识,通过 8 个真实场景的端到端诊断实践——OOM Killer 分析、D 状态进程排查、调度延迟分析、I/O 瓶颈定位、网络丢包排查、内存泄漏追踪、容器隔离验证、系统启动优化——建立问题定位的通用方法论。
3
中断与软中断
Linux内核 深入解析 Linux 中断与延迟处理机制——IDT 中断描述符表、硬件中断处理流程、Top Half/Bottom Half 分离、Softirq 9种类型、Tasklet 动态注册、Workqueue 可睡眠延迟工作、IRQ Affinity 多核中断分发。
4
Cgroups 与 Namespaces
Linux内核 深入解析容器技术的内核根基——7 种 Linux Namespace 实现资源视图隔离、Cgroup v1/v2 控制器实现资源限制、unshare/setns 系统调用、容器运行时如何使用 cgroup+namespace——从容器到 Kubernetes 的内核视角。
5
块设备与 I/O 栈
Linux内核 深入解析 Linux 块设备与 I/O 栈——bio 请求结构、通用块层与 blk-mq 多队列设计、I/O 调度器演进(CFQ→Deadline→BFQ)、I/O 合并与排序、NVMe 驱动模型——从 I/O 请求到磁盘的完整路径。