内核调试

一、printk

1. 基本用法

printk(KERN_INFO "msg\n");          // 老 API
pr_info("msg %d\n", x);             // 推荐
pr_err("error %d\n", x);
pr_warn("warning\n");
dev_info(dev, "msg");               // 自动加设备名
dev_err(dev, "msg");

// 日志级别
#define KERN_EMERG    "<0>"   // 系统不可用
#define KERN_ALERT    "<1>"   // 必须立即处理
#define KERN_CRIT     "<2>"   // 严重
#define KERN_ERR      "<3>"   // 错误
#define KERN_WARNING  "<4>"   // 警告
#define KERN_NOTICE   "<5>"   // 正常但重要
#define KERN_INFO     "<6>"   // 信息
#define KERN_DEBUG    "<7>"   // 调试

2. 控制台日志级别

# 查看 / 设置
cat /proc/sys/kernel/printk
echo 8 > /proc/sys/kernel/printk       # 所有级别都打
dmesg -n 8
dmesg -w                              # 实时
dmesg -c                              # 清空

# 内核启动参数
loglevel=7
ignore_loglevel
quiet

3. ratelimited(防刷屏)

pr_info_ratelimited("...");
dev_info_ratelimited(dev, "...");

二、Dynamic Debug

# 启用
echo "file drivers/gpio/gpiolib.c +p" > /sys/kernel/debug/dynamic_debug/control
echo "module mymodule +p" > /sys/kernel/debug/dynamic_debug/control
echo "func my_probe +p" > /sys/kernel/debug/dynamic_debug/control

# 全部
echo "+p" > /sys/kernel/debug/dynamic_debug/control

# 关闭
echo "file gpiolib.c -p" > /sys/kernel/debug/dynamic_debug/control

源码中:

pr_debug("value: %d\n", val);   // 需要 CONFIG_DYNAMIC_DEBUG

三、dump_stack

WARN_ON(condition);
BUG_ON(condition);
dump_stack();                   // 打印调用栈
WARN(1, "msg");

四、kgdb / kdb

五、oops / panic 分析

# 内核配置
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_INFO=y

# 保存 oops
dmesg > oops.txt

# 用 addr2line / decode
addr2line -e vmlinux 0xc0123456
gdb vmlinux
(gdb) list *0xc0123456

六、ftrace

mount -t tracefs none /sys/kernel/tracing

# 函数跟踪
echo function > /sys/kernel/tracing/current_tracer
echo my_func > /sys/kernel/tracing/set_ftrace_filter
echo 1 > /sys/kernel/tracing/tracing_on
cat /sys/kernel/tracing/trace
echo 0 > /sys/kernel/tracing/tracing_on

# trace-cmd(推荐工具)
trace-cmd record -p function -l my_func ls
trace-cmd report

# 其他 tracer
function_graph
wakeup_rt
irqsoff
preemptoff

七、perf

# 列出事件
perf list

# record / report
perf record -g -e cycles -a sleep 5
perf report

# 调度延迟
perf sched record sleep 5
perf sched latency

# cache 命中率
perf stat -e cache-misses,cache-references ls

# 函数采样
perf top
perf top -e cpu-clock

# tracepoint
perf record -e sched:sched_switch -a
perf script

# 锁竞争
perf lock contention -a

八、eBPF / bcc / bpftrace

# bpftrace
bpftrace -e 'kprobe:do_sys_open { printf("%s\n", argstr(1)); }'

# bcc 工具
opensnoop-bpfcc
execsnoop-bpfcc
tcpconnect-bpfcc
biolatency-bpfcc
runqlat-bpfcc
softirqs-bpfcc

九、kprobes / uprobes

// 内核模块动态追踪
// 见 samples/kprobes/

十、Crashdump / kdump

# 安装
apt install kdump-tools
# 配置 /etc/default/kdump-tools
USE_KDUMP=1

# 触发
echo c > /proc/sysrq-trigger     # SysRq-C:触发 panic

# 分析
crash /usr/lib/debug/vmlinux /var/crash/2026*/vmcore
crash> bt
crash> log
crash> ps

十一、SysRq

# 启用
echo 1 > /proc/sys/kernel/sysrq

# 远程触发
echo t > /proc/sysrq-trigger      # 任务状态
echo m > /proc/sysrq-trigger      # 内存
echo w > /proc/sysrq-trigger      # 阻塞任务
echo l > /proc/sysrq-trigger      # CPU 注册
echo s > /proc/sysrq-trigger      # 同步
echo u > /proc/sysrq-trigger      # 重挂载只读
echo b > /proc/sysrq-trigger      # 重启(慎用!)
echo c > /proc/sysrq-trigger      # panic(触发 crashdump)
echo h > /proc/sysrq-trigger      # 帮助

十二、strace / ltrace

strace -e openat,read,write -p PID
strace -c -p PID                 # 统计
strace -f -e trace=network cmd

十三、devmem

# 读物理地址
devmem 0x40010000 32
devmem 0x40010000 16
# 写
devmem 0x40010000 32 0x12345678

十四、lockdep

# 启用
echo 1 > /proc/sys/kernel/lock_stat
cat /proc/lock_stat
# 锁错误会打印调用链

十五、UBSan / KASan / KMSan

# 内核配置
CONFIG_UBSAN=y
CONFIG_KASAN=y
CONFIG_KMSAN=y
CONFIG_KCSAN=y            # 数据竞争检测

# 报告
dmesg | grep -E "KASAN|UBSAN|KMSAN"

十六、调试工具汇总

工具 用途
printk 日志
dmesg 看内核日志
ftrace 函数追踪、延迟
perf 性能分析、采样
bpftrace 高级追踪
kgdb 远程调试
crash core dump 分析
devmem 物理内存读
devlink 设备调试
i2c-tools / spidev / spidev_test 总线调试
strace 用户态跟踪