返回列表 发布新帖
查看: 138|回复: 0

Linux设备驱动调试实战指南

988

主题

0

回帖

833

积分

高级会员

积分
833
发表于 昨天 10:10 | 查看全部 |阅读模式
聊聊 Linux 设备驱动调试方法的一点经验

做 Linux 设备驱动,最容易踩的坑不是代码写不出来,而是问题出现时不知道从哪里下手。驱动问题通常不像应用程序那样直接报个异常就结束,它可能表现为设备没反应、偶发超时、系统卡死、内核 panic,甚至只是“偶尔不稳定”。所以我一直觉得,驱动调试最重要的不是工具多,而是先把思路理清楚。

最基础的还是 printk 和 dmesg。很多人嫌它土,但真到板子刚起来、调试环境不完整的时候,它往往是最可靠的办法。不过 printk 不能乱打,尤其是中断、定时器、频繁调用路径里,打印太多会改变时序,甚至把问题掩盖掉。我的习惯是打印关键状态:寄存器值、返回码、状态机变化、超时点,而不是每走一行都打印。

如果驱动已经比较稳定,但需要定位某个分支或流程,dynamic debug 很好用。它可以在不重新编译内核的情况下打开某些文件、某些函数里的调试信息,比到处加 printk 干净很多。配合 trace_printk、ftrace、trace-cmd 这类工具,可以看函数调用路径和耗时,对定位性能问题、调用顺序问题特别有帮助。

硬件相关驱动一定不要只盯着软件日志。比如 I2C、SPI、UART、GPIO、中断线这些,逻辑分析仪和示波器经常比内核日志更诚实。代码里写了发送,不代表线上真的发了;中断处理函数进了,不代表中断边沿符合芯片手册要求。遇到“驱动看起来没错但设备就是不动”的情况,我一般会先抓波形,再回头看代码。

内核自带的调试选项也值得打开,比如 lockdep、KASAN、KCSAN、kmemleak。很多驱动 bug 表面上是随机崩溃,实际是越界、重复释放、竞态或者锁顺序问题。这类问题靠肉眼看代码很难发现,打开这些检查项后,虽然性能会下降,但能节省大量时间。调试阶段不要怕内核“吵”,它吵出来的信息往往就是线索。

对于崩溃类问题,保存现场很关键。串口日志、完整 oops、调用栈、寄存器、触发步骤都要留。条件允许的话可以配置 kdump,拿到 vmcore 后用 crash 分析,比只看最后几行 panic 信息靠谱得多。很多时候真正的出错点不在 panic 的地方,而是在更早之前内存已经被破坏了。

另外,sysfs、debugfs、procfs 这些接口也可以为驱动调试服务。适当暴露一些内部状态,比如当前模式、计数器、错误码、寄存器快照,可以避免频繁改代码重编译。但要注意调试接口不要随手留到正式产品里,尤其是能直接改寄存器或控制电源的接口,后期很容易变成安全隐患。

最后我想说,驱动调试不要迷信单一工具。一个有效的流程通常是:先复现问题,再缩小范围,然后用日志确认软件路径,用波形确认硬件行为,用内核调试工具查内存和并发问题。很多“玄学问题”其实都是信息不够导致的。把证据收集完整,问题往往就没那么玄了。
回复 转播

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关灯 在本版发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表