在第 17 章中,我们学习了如何通过内核模块扩展内核功能,也提到了 printk 这个最朴素的调试手段。但 printk 有一个致命的局限——它只能输出你预先编码的信息。当生产环境出现偶发性延迟、吞吐量骤降或死锁时,你不可能提前在每一行可疑代码里插入 printk,更不可能为了加一条日志而重新编译和加载内核模块。
你需要的是一种无需修改内核源码、开销极低、能在线上实时运行的观测能力。这就是 Linux 内核追踪与可观测性(Tracing & Observability) 体系要解决的核心问题。
本章将从可观测性的演进历史出发,依次深入 ftrace、perf、eBPF 三大核心工具,最后介绍 bpftrace 和 BCC 这两个让 eBPF 真正走向生产的高层接口。
一、可观测性的演进:从 printk 到 eBPF
Linux 内核的可观测性工具经历了一条清晰的演进路径——从最原始的日志输出,到静态追踪点,再到完全可编程的动态追踪框架:
| 阶段 | 工具 | 能力 | 开销 | 可编程性 |
|---|---|---|---|---|
| 日志输出 | printk | 输出预定义信息 | 高(I/O 锁竞争) | 无 |
| 函数追踪 | ftrace | 追踪函数调用/返回 | 中(动态插桩) | 有限 |
| 性能计数 | perf | 采样 + 硬件计数器 | 低(采样率可调) | 有限 |
| 可编程追踪 | eBPF | 在内核安全执行自定义逻辑 | 极低(JIT 编译) | 完全 |
这四个阶段并非替代关系,而是互补关系。printk 仍然是开发阶段的首选调试手段;ftrace 在函数级追踪上无可替代;perf 是性能剖析的瑞士军刀;eBPF 则将可观测性推向了可编程的新高度。生产环境中,它们往往配合使用。
二、ftrace:内核函数追踪器
ftrace 是 Linux 内核内置的追踪框架,名字源自”function tracer”,但其能力远不止函数追踪——它还支持事件追踪、函数图形化追踪、延迟追踪等多种模式。ftrace 的所有功能通过 debugfs(通常挂载在 /sys/kernel/debug/tracing)暴露给用户空间。
2.1 动态插桩机制:-pg、mcount 与 fentry
ftrace 的核心问题是:如何在不修改内核源码的情况下,在任意函数入口插入追踪代码?答案依赖于编译器的配合和运行时的动态修补:
传统方式(x86 32 位 / 早期内核):
- 编译内核时,GCC 的
-pg选项在每个函数入口插入一条call mcount指令 - 默认情况下,
mcount是一个空函数,直接返回——几乎零开销 - 启用追踪时,ftrace 将
mcount处的call指令动态替换为call ftrace_caller ftrace_caller保存上下文后调用用户注册的追踪回调函数
现代方式(x86_64 / GCC 5.0+ / Clang):
- 编译器在每个函数入口插入
call __fentry__(GCC)或call __cyg_profile_func_enter(Clang) - 内核使用
ftrace_patch_location结构记录每个插桩点的位置 - 启用追踪时,通过
text_poke机制将call __fentry__替换为跳转到追踪处理器的指令
关键源码位于:
kernel/trace/ftrace.c— ftrace 核心逻辑include/linux/ftrace.h— ftrace 接口定义arch/x86/kernel/ftrace.c— x86 架构相关的动态插桩实现
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_nanosleep2.3 function_graph 追踪器
function_graph 不仅记录函数入口,还记录函数返回,从而展示完整的调用栈和执行时间:
echo function_graph > /sys/kernel/debug/tracing/current_tracerecho '*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/enabletrace-cmd 是 ftrace 的前端工具,大幅简化了操作流程:
# 安装 trace-cmdsudo 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):
| 事件 | 含义 | 典型用途 |
|---|---|---|
cycles | CPU 周期数 | 计算指令吞吐量 |
instructions | 已执行指令数 | 计算 CPI(Cycles Per Instruction) |
cache-references | 缓存引用次数 | 评估缓存压力 |
cache-misses | 缓存未命中次数 | 计算缓存命中率 |
branch-misses | 分支预测失败次数 | 评估分支预测效率 |
stalled-cycles-frontend | 前端停顿周期 | 指令获取瓶颈 |
stalled-cycles-backend | 后端停顿周期 | 执行单元瓶颈 |
软件事件(来自内核统计):
| 事件 | 含义 |
|---|---|
cpu-clock | CPU 时钟任务 |
task-clock | 任务时钟 |
page-faults | 缺页异常 |
context-switches | 上下文切换 |
cpu-migrations | CPU 迁移 |
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缓存命中率是评估程序数据局部性的关键指标:
命中率低于 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 reportperf 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-misses3.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),实现内核数据结构的类型信息传递
4.2 eBPF 程序类型
eBPF 程序不是”一段通用代码”,而是针对特定钩子点类型编写的专用程序。内核定义了数十种程序类型(enum bpf_prog_type),每种类型决定了程序可以挂载的位置、可以调用的辅助函数、可以访问的上下文数据:
| 程序类型 | 钩子点 | 典型用途 |
|---|---|---|
BPF_PROG_TYPE_KPROBE | 内核函数入口/返回 | 追踪内核函数行为 |
BPF_PROG_TYPE_TRACEPOINT | 静态追踪点 | 低开销事件追踪 |
BPF_PROG_TYPE_PERF_EVENT | perf 事件 | 性能计数器驱动的采样 |
BPF_PROG_TYPE_XDP | 网络驱动收包路径 | DDoS 防御、负载均衡 |
BPF_PROG_TYPE_SCHED_CLS | tc 流量控制 | 网络流量分类与标记 |
BPF_PROG_TYPE_CGROUP_SKB | cgroup 网络钩子 | 容器网络策略 |
BPF_PROG_TYPE_SOCKET_FILTER | 套接字消息过滤 | 网络包过滤 |
BPF_PROG_TYPE_LSM | Linux 安全模块 | 安全策略执行 |
程序类型的定义位于 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_ARRAY | perf 事件数组 | 向用户空间发送事件 |
BPF_MAP_TYPE_RINGBUF | 环形缓冲区 | 高效事件流传输 |
BPF_MAP_TYPE_STACK_TRACE | 调用栈存储 | 火焰图数据采集 |
BPF_MAP_TYPE_LRU_HASH | LRU 哈希表 | 有限容量的缓存 |
在 eBPF 程序中,通过 bpf_map_lookup_elem()、bpf_map_update_elem() 等辅助函数操作 Map;在用户空间,通过 bpf() 系统调用的 BPF_MAP_LOOKUP_ELEM、BPF_MAP_UPDATE_ELEM 等命令读写 Map。
BPF_MAP_TYPE_PERCPU_HASH 是高性能场景的首选——每个 CPU 拥有独立的哈希表副本,eBPF 程序写入时无需加锁,用户空间读取时再合并各 CPU 的数据。这利用了第 14 章中 per-CPU 变量的思想:通过空间换时间,消除锁竞争。
4.4 BPF 验证器:安全的基石
eBPF 允许普通用户向内核注入代码——这在安全上是极度危险的。BPF 验证器(Verifier)是 eBPF 安全模型的基石,它在程序加载时进行静态分析,确保程序不会危害内核的稳定性:
验证器的核心检查包括:
- DAG 检查:程序必须是无环的有向无环图(DAG),不允许循环——确保程序必定终止
- 指令数上限:早期限制为 4096 条指令,5.2+ 内核通过
bpf2bpf调用链支持最多 8 层嵌套函数调用,总指令数上限为 100 万条 - 寄存器状态追踪:验证器模拟执行程序,追踪每个寄存器可能的值范围(scalar range)和类型(指针、Map 值、上下文等),确保不会发生越界访问
- 空指针检查:所有指针解引用前必须经过 NULL 检查
- 越界访问检查:所有内存访问必须在已验证的范围内
- 辅助函数权限:不同程序类型只能调用特定的辅助函数子集
验证器的源码位于 kernel/bpf/verifier.c——这是内核中最复杂的代码之一,超过 20000 行,实现了基于抽象解释(Abstract Interpretation)的数据流分析。
验证器的错误信息有时晦涩难懂。当你的 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 模式 |
cpudist | CPU on/off 时间分布 | 评估 CPU 利用率 |
offcputime | 离 CPU 时间追踪 | 定位线程阻塞原因 |
slabratetop | Slab 分配速率排行 | 内存分配热点 |
tcpconnect | 追踪 TCP 主动连接 | 网络连接审计 |
tcpaccept | 追踪 TCP 被动接受 | 服务端连接监控 |
tcplife | TCP 连接生命周期 | 连接时长统计 |
tcpretrans | TCP 重传事件 | 网络质量评估 |
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 的协作
三大工具各有侧重,在实际排查中往往需要组合使用:
- 先用
perf top定位热点函数——快速缩小范围 - 再用
ftrace function_graph分析调用路径——理解执行流 - 最后用 eBPF 精确度量——在热点路径上插入计数器、直方图、延迟追踪
# 第一步:perf 定位热点sudo perf top -g
# 第二步:ftrace 分析调用路径sudo trace-cmd record -p function_graph -l hot_function sleep 5sudo 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 3sudo trace-cmd report | head -50
# 追踪 sched_switch 事件sudo trace-cmd record -e sched:sched_switch sleep 5sudo 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 10perf script | stackcollapse-perf.pl | flamegraph.pl > flamegraph.svg
# 实时查看内核热点sudo perf top -k /boot/vmlinux-$(uname -r)实践三:使用 bpftrace 追踪内核函数
# 安装 bpftracesudo 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 工具集
# 安装 BCCsudo 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)BCC 工具在 Ubuntu/Debian 上的命令名带有 -bpfcc 后缀(如 execsnoop-bpfcc),在 RHEL/CentOS 上则没有后缀(如 execsnoop)。这是因为 BCC 工具与系统自带的旧版本同名,需要通过后缀区分。
实践五:对比 ftrace 与 eBPF 的开销
# 使用 ftrace 追踪 schedule 函数,测量开销echo nop > /sys/kernel/debug/tracing/current_tracerecho 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
# 启用 ftraceecho function > /sys/kernel/debug/tracing/current_tracerecho 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.h | ftrace 接口与数据结构定义 |
include/uapi/linux/bpf.h | eBPF 用户态 API(程序类型、Map 类型、辅助函数) |
include/trace/events/ | 内核静态追踪点定义 |
arch/x86/kernel/ftrace.c | x86 架构 ftrace 动态插桩实现 |
官方文档
- ftrace Documentation — ftrace 官方文档
- eBPF Documentation — eBPF 官方文档与生态
- perf Wiki — perf 工具官方 Wiki
- BPF & XDP Reference — Cilium 项目的 BPF 参考文档
手册页
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 Gregg | eBPF 性能工具的权威指南 |
| 《Linux Observability with BPF》 | David Calavera 等 | eBPF 可观测性实践 |
| 《Learning eBPF》 | Liz Rice | eBPF 入门与实战 |
在线资源
- Brendan Gregg’s Linux Performance — 性能分析参考大全
- bpftrace Reference Guide — bpftrace 语法参考
- BCC Tools Reference — BCC 工具使用指南
- eBPF.io — eBPF 生态门户
从 printk 到 ftrace,从 perf 到 eBPF,Linux 内核的可观测性体系走过了一条从”看日志”到”可编程观测”的演进之路。ftrace 能追踪内核的每一步执行,perf 能精确度量性能瓶颈,eBPF 则将两者统一在一个安全、高效、可编程的框架之下。而 bpftrace 和 BCC 让 eBPF 的能力触手可及——一行命令就能洞察内核的内部运作。
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






