printk是内核中最基本的调试方法,类似于用户空间的printf。
printk(KERN_DEBUG "Debug message: value=%d\n", var);
dmesg -H # 人性化显示
dmesg -w # 实时监视
dmesg -l debug # 只显示debug级别消息
更灵活的printk替代方案,可以运行时启用/禁用调试消息。
pr_debug("Debug message with %s\n", "dynamic debug");
配置方法:
# 查看所有可调试点
cat /sys/kernel/debug/dynamic_debug/control
# 启用特定文件的调试
echo 'file module.c +p' > /sys/kernel/debug/dynamic_debug/control
# 启用特定函数的调试
echo 'func foo +p' > /sys/kernel/debug/dynamic_debug/control
kprobes允许在内核的任何指令处设置断点。
# 安装kprobe工具
apt-get install linux-tools-$(uname -r)
# 跟踪特定函数
perf probe --add vfs_read
perf stat -e probe:vfs_read -a sleep 10
perf probe --del vfs_read
# 列出所有可探测的函数
cat /proc/kallsyms | grep function_name
# 设置探测点
echo 'p:myprobe do_sys_open' > /sys/kernel/debug/tracing/kprobe_events
echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable
# 查看结果
cat /sys/kernel/debug/tracing/trace_pipe
ftrace是内核内置的函数跟踪器。
# 启用ftrace
echo function > /sys/kernel/debug/tracing/current_tracer
echo 1 > /sys/kernel/debug/tracing/tracing_on
# 查看结果
cat /sys/kernel/debug/tracing/trace
# 只跟踪特定函数
echo schedule > /sys/kernel/debug/tracing/set_ftrace_filter
# 函数图跟踪
echo function_graph > /sys/kernel/debug/tracing/current_tracer
# 跟踪特定进程
echo $$ > /sys/kernel/debug/tracing/set_ftrace_pid
# 跟踪特定模块
echo ':mod:module_name' > /sys/kernel/debug/tracing/set_ftrace_filter
SystemTap提供了强大的脚本语言来监控和分析运行中的Linux系统。
probe kernel.function("sys_open") {
printf("%s(%s)\n", probefunc(), user_string($filename))
}
stap -ve 'probe begin { log("hello world") exit() }'
stap -L 'kernel.function("vfs_read")'
stap script.stp -o output.log
KGDB允许通过串口或网络对Linux内核进行源代码级调试。
kgdboc=ttyS0,115200 kgdbwait
target remote /dev/ttyS0
break function_name
continue
用于分析内核崩溃转储。
# 安装必要工具
apt-get install kdump-tools crash
# 配置/etc/default/kdump-tools
KDUMP_COREDIR="/var/crash"
crash /usr/lib/debug/boot/vmlinux-$(uname -r) /var/crash/dump.20191010
常用命令:
bt # 查看调用栈
log # 查看内核日志
kmem # 查看内存信息
task # 查看任务信息
用于检测内存错误,如越界访问、释放后使用等。
配置内核选项:
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y
用于检测内核内存泄漏。
# 启用
echo scan > /sys/kernel/debug/kmemleak
# 查看报告
cat /sys/kernel/debug/kmemleak
perf top # 实时查看热点函数
perf record -a -g # 记录性能数据
perf report # 分析记录数据
perf stat -e instructions,cache-misses ./program
# 使用BCC工具
/usr/share/bcc/tools/execsnoop
# 使用BPFtrace
bpftrace -e 'tracepoint:syscalls:sys_enter_open { printf("%s %s\n", comm, str(args->filename)); }'
# 查看模块依赖
modinfo module_name
# 加载模块时打印调试信息
insmod module.ko dyndbg=+p
# 查看模块参数
cat /sys/module/module_name/parameters/*
当内核遇到严重错误时会产生Oops消息,包含: - 错误类型和地址 - CPU寄存器状态 - 调用栈回溯
分析方法:
1. 确保内核配置了CONFIG_DEBUG_INFO=y
2. 使用gdb或crash工具分析Oops消息
根据调试场景选择合适的方法: - 简单调试:printk/dynamic debug - 函数调用跟踪:ftrace/kprobes - 复杂逻辑分析:SystemTap/BPF - 崩溃分析:Kdump/crash - 内存问题:KASAN/kmemleak - 性能分析:perf/BPF
掌握这些工具的组合使用可以高效定位各种内核模块问题。