1. 课程导入

Linux设备模型是内核中用于统一描述设备、驱动与总线之间关系的核心基础设施。它并非一个孤立的子系统,而是贯穿设备注册、驱动匹配、电源管理、热插拔、sysfs 导出等多条关键路径的“骨架”。在实际工程中,大量看似互不相关的故障——例如驱动加载了但设备不工作、/sys 下节点缺失、probe 函数迟迟不执行、设备树节点被忽略——最终都会追溯到设备模型中的某个环节。因此,本课程的目标不是背诵数据结构,而是建立一套可观测、可推理、可定位的调试方法论。

一、学习目标:从“看懂代码”到“定位故障”

本课程围绕三个层次递进展开。第一层是结构认知:理解 kobject、kset、device、driver、bus、class 等对象之间的从属与引用关系。第二层是路径追踪:能够沿着“设备注册 → 总线匹配 → 驱动 probe → sysfs 呈现”的主链路,判断故障发生在哪一段。第三层是实战定位:借助 sysfs、debugfs、ftrace、dmesg、devlink 等工具,把抽象关系转化为可读的现场证据。

学习完成后,你应当能够回答:一个设备为什么没有出现在 /sys/devices 下?驱动为什么没有绑定到设备?probe 为什么返回 -EPROBE_DEFER?删除设备后引用计数为什么没有归零?

二、核心概念:设备模型的“四梁八柱”

设备模型的核心可以概括为“三类对象、两条关系、一个视图”。三类对象是设备(device)、驱动(driver)和总线(bus);两条关系是归属关系(设备挂在总线上、驱动注册到总线上)和匹配关系(总线负责将设备与驱动配对);一个视图是sysfs 视图,它把内核对象以文件和目录的形式暴露给用户空间。

  • kobject:引用计数与 sysfs 目录的最小单元,是设备模型的地基。
  • kset:kobject 的集合,用于组织层级和统一管理。
  • device:描述一个具体硬件或逻辑设备,包含父设备、总线、驱动指针。
  • device_driver:描述驱动能力,包含 id_table、probe、remove 等回调。
  • bus_type:定义匹配规则(match)和探测入口(probe),是设备与驱动的“红娘”。
  • class:从功能角度对设备分类,如 input、net、tty,影响 /sys/class 下的呈现。

理解这些对象的关键,不在于记住字段,而在于记住它们之间的指针方向和生命周期。例如,device 通过 bus 找到 driver,driver 通过 bus 找到 device;当两者匹配成功,bus 调用 driver 的 probe,并把 device 传给驱动。任何一环的指针为空或引用计数异常,都会表现为“设备不工作”。

三、整体知识框架与实战路线图

下图给出了本课程的整体知识框架:左侧是设备模型的核心对象与关系,中间是调试与故障定位的主路径,右侧是常用工具与观测点。它既是知识地图,也是后续章节的实战路线图。

Linux 设备模型调试与故障定位 · 知识框架与实战路线 核心对象与关系 bus_type(总线) device(设备) device_driver(驱动) class(功能分类) kobject / kset 调试与故障定位主路径 ① 设备注册:device_register / of_platform ② 总线匹配:match() 比较 id / compatible ③ 驱动探测:probe() 执行与返回值 ④ sysfs 呈现:/sys/devices 与 /sys/class ⑤ 生命周期:引用计数、remove、unbind ⑥ 故障复盘:日志、trace、状态快照 工具与观测点 dmesg / 内核日志 sysfs:/sys/bus、/sys/devices debugfs:/sys/kernel/debug ftrace / tracepoint devlink / udevadm pstore / ramoops

四、典型场景:从现象到根因的推理链

假设你插入一个 USB 网卡,lsusb 能看到设备,但 ip link 没有新增网口。按照设备模型路径,可以快速缩小范围:

  1. 检查 /sys/bus/usb/devices/ 下是否有对应设备节点,确认 USB 核心层是否枚举成功。
  2. 检查 /sys/bus/usb/drivers/ 下目标驱动目录中是否有该设备的符号链接,确认匹配是否发生。
  3. 若未匹配,查看 dmesg 中是否有 usb 1-1: new high-speed USB device 之后的 probe failed 或 no driver 信息。
  4. 若已匹配但无网口,检查驱动 probe 是否返回 -EPROBE_DEFER,这通常意味着依赖的时钟、电源或 PHY 尚未就绪。

这条推理链的价值在于:它把“网卡不工作”这个模糊现象,拆解为设备枚举、总线匹配、驱动探测、功能注册四个可独立验证的检查点。每个检查点都有对应的 sysfs 路径和日志关键字,而不是靠猜测。

五、常见误区与复盘要点

误区一:只看驱动代码,不看设备模型状态。很多 probe 失败并非驱动逻辑错误,而是设备根本没有被正确注册,或总线匹配条件不满足。先确认 /sys 下的对象是否存在,再读代码。
误区二:把 /sys/class 和 /sys/devices 混为一谈。前者是功能视图,后者是物理/拓扑视图。设备可能出现在 /sys/devices 但未出现在 /sys/class,这通常说明 class 注册或 device_add 的 class 关联环节有问题。
复盘建议:每次定位完一个设备模型问题,记录三样东西——故障现象、关键 sysfs 路径、最终根因所在的对象(device / driver / bus / class)。积累十次以上,你会形成自己的“设备模型故障模式库”。

六、关键命令与观测入口速查

观测目标命令或路径典型用途
设备是否注册ls /sys/devices/确认设备对象是否出现在拓扑中
驱动是否绑定ls -l /sys/bus/*/drivers/*/查看设备与驱动的符号链接
总线匹配信息cat /sys/bus/usb/devices/*/uevent查看设备 uevent 与匹配属性
probe 返回值dmesg | grep -i probe定位 probe 失败或 defer 原因
引用计数cat /sys/kernel/debug/kobject/*排查对象无法释放问题
设备树节点ls /proc/device-tree/确认 DT 节点是否被内核解析
# 快速查看某设备是否绑定驱动
ls -l /sys/bus/platform/devices/ | grep -i uart
ls -l /sys/bus/platform/drivers/ | grep -i uart

# 查看设备 uevent 与驱动匹配信息
cat /sys/bus/platform/devices/fe001000.serial/uevent

# 过滤 probe 相关日志
dmesg | grep -Ei "probe|defer|failed|bind"