1. 课程导入
Linux设备模型是内核中用于统一描述设备、驱动与总线之间关系的核心基础设施。它并非一个孤立的子系统,而是贯穿设备注册、驱动匹配、电源管理、热插拔、sysfs 导出等多条关键路径的“骨架”。在实际工程中,大量看似互不相关的故障——例如驱动加载了但设备不工作、/sys 下节点缺失、probe 函数迟迟不执行、设备树节点被忽略——最终都会追溯到设备模型中的某个环节。因此,本课程的目标不是背诵数据结构,而是建立一套可观测、可推理、可定位的调试方法论。
一、学习目标:从“看懂代码”到“定位故障”
本课程围绕三个层次递进展开。第一层是结构认知:理解 kobject、kset、device、driver、bus、class 等对象之间的从属与引用关系。第二层是路径追踪:能够沿着“设备注册 → 总线匹配 → 驱动 probe → sysfs 呈现”的主链路,判断故障发生在哪一段。第三层是实战定位:借助 sysfs、debugfs、ftrace、dmesg、devlink 等工具,把抽象关系转化为可读的现场证据。
二、核心概念:设备模型的“四梁八柱”
设备模型的核心可以概括为“三类对象、两条关系、一个视图”。三类对象是设备(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 传给驱动。任何一环的指针为空或引用计数异常,都会表现为“设备不工作”。
三、整体知识框架与实战路线图
下图给出了本课程的整体知识框架:左侧是设备模型的核心对象与关系,中间是调试与故障定位的主路径,右侧是常用工具与观测点。它既是知识地图,也是后续章节的实战路线图。
四、典型场景:从现象到根因的推理链
假设你插入一个 USB 网卡,lsusb 能看到设备,但 ip link 没有新增网口。按照设备模型路径,可以快速缩小范围:
- 检查
/sys/bus/usb/devices/下是否有对应设备节点,确认 USB 核心层是否枚举成功。 - 检查
/sys/bus/usb/drivers/下目标驱动目录中是否有该设备的符号链接,确认匹配是否发生。 - 若未匹配,查看
dmesg中是否有usb 1-1: new high-speed USB device之后的probe failed或no driver信息。 - 若已匹配但无网口,检查驱动 probe 是否返回
-EPROBE_DEFER,这通常意味着依赖的时钟、电源或 PHY 尚未就绪。
这条推理链的价值在于:它把“网卡不工作”这个模糊现象,拆解为设备枚举、总线匹配、驱动探测、功能注册四个可独立验证的检查点。每个检查点都有对应的 sysfs 路径和日志关键字,而不是靠猜测。
五、常见误区与复盘要点
/sys 下的对象是否存在,再读代码。
/sys/class 和 /sys/devices 混为一谈。前者是功能视图,后者是物理/拓扑视图。设备可能出现在 /sys/devices 但未出现在 /sys/class,这通常说明 class 注册或 device_add 的 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"