第4章 基础调试工具:dmesg日志分析、/sys/kernel/debug/usb目录结构、usbmon工具安装与基本使用
做USB OTG调试,工具就是我们的眼睛和耳朵。我个人习惯先把这三个基础工具摸透:dmesg、debugfs下的usb目录、还有usbmon。它们分别从日志、状态和原始流量三个维度给你信息。就像修车先看仪表盘,再掀引擎盖,最后挂示波器一样。
1. dmesg日志分析
dmesg输出的是内核日志环缓冲区的内容。USB枚举、驱动绑定、电源事件、错误信息,全在这里。我用dmesg排查过不下上百次USB问题,每次都是第一站。
- 实时监控:
sudo dmesg -w或者sudo dmesg -W(等着看新消息) - 过滤USB:
sudo dmesg | grep -i usb - 只看某个设备:插拔后记下设备号,再
sudo dmesg | grep -E "usb 1-2|hub 1-0"
有一次,我接到一个案子:设备插上后系统死锁。一查dmesg,发现是usb_submit_urb一直返回-ENOMEM,然后用cat /proc/meminfo一看,DMA buffer耗尽——原来是驱动忘了释放。这种场景,没dmesg根本定位不了。
sudo dmesg -c清空,或者用dmesg -T打上时间戳以便回溯。
2. /sys/kernel/debug/usb目录结构
debugfs里的USB节点,是内核USB子系统的“实时状态快照”。你想要的设备描述符、端点配置、当前电源状态、甚至HCD的调度信息,都能在这里找到。我一遇到设备枚举失败,第一步看dmesg,第二步就进这个目录。
典型路径:
/sys/kernel/debug/usb/devices– 所有USB设备的完整树形信息,包括速度、配置、接口、端点/sys/kernel/debug/usb/<busnum>-<port>/...– 按拓扑组织的设备级debug信息/sys/kernel/debug/usb/hcd/– HCD(主机控制器驱动)的一些调度统计
举个例子,你想看某个设备是否进入了suspend状态:
cat /sys/kernel/debug/usb/devices | grep "S:"
# S: 开头的行显示当前状态(S0=正常, S2=挂起, S3=暂停等)
/sys/kernel/debug/usb/devices和/sys/class/power_supply/usb/。如果设备角色从Host变成Peripheral,但状态字还是“S0”,说明驱动层没响应,往往就是电源通知没送达。
3. usbmon工具安装与基本使用
usbmon是内核内置的USB流量嗅探器,能捕获所有URB(USB请求块)的细节。它不需要额外硬件,一根数据线就能当逻辑分析仪用。
安装与启用:
- 检查内核模块:
lsmod | grep usbmon,如果没有,加载:sudo modprobe usbmon - 查看可用接口:
ls /sys/kernel/debug/usb/usbmon/,会看到0s、1s、1t等文件:0s代表所有总线汇总,1s代表总线1的文本输出,1t是二进制格式(配合Wireshark用) - 抓取文本日志:
sudo cat /sys/kernel/debug/usb/usbmon/1s > usb_trace.log,然后操作设备,结束后Ctrl+C - 结合Wireshark:
sudo cat /sys/kernel/debug/usb/usbmon/1t | wireshark -k -i -,在线实时分析
| usbmon接口 | 输出格式 | 使用场景 |
|---|---|---|
| 0s | 纯文本(所有总线汇总) | 快速查看全局流量,但缺少总线号信息 |
| 1s | 纯文本(仅总线1) | 日常调试,grep过滤 |
| 1t | 二进制(pcap格式) | 导入Wireshark进行详细分析 |
1-2.3),然后grep usbmon日志:grep "1-2.3" usb_trace.log。我自己就把这个别名写成了 usbmon-grep 脚本,省了很多事。
我曾经遇到一个UVC摄像头画面卡顿的问题。dmesg没报错,debugfs显示设备状态正常。最后用usbmon抓流量,发现每隔几秒就有一次URB提交超时,原因是中断端点上的NAK太多。配合Wireshark看时间戳,确认是USB带宽竞争导致。调了QoS就解决了。
三者联动:调试流程
下面这张图,是我常用的三板斧配合套路:
实际调的时候,我通常会先在dmesg里跑一圈排除明显错误,再钻进debugfs看设备状态和端点配置,最后才上usbmon抓流量。这三板斧几乎能覆盖日常90%的USB问题。