2. Linux设备模型基础
Linux设备模型是内核为统一管理硬件而抽象出的一套对象关系框架。它把“设备”“驱动”“总线”“类”“子系统”等概念组织成可枚举、可匹配、可挂载、可观察的结构,并通过sysfs、devtmpfs、udev把内核内部状态暴露给用户空间。理解这五类对象与三个用户空间接口的关系,是掌握设备生命周期与资源管理的第一步。
一、核心对象:设备、驱动、总线、类、子系统
在Linux设备模型中,设备(device)表示一个具体的硬件实例或逻辑功能节点,例如一块网卡、一个GPIO控制器、一个USB接口。设备对象通常由struct device描述,它记录父设备、所属总线、驱动绑定状态、电源管理信息等。
驱动(driver)是操作设备的代码集合,通常由struct device_driver描述。驱动并不直接“拥有”设备,而是向总线注册自己,声明能匹配哪些设备。匹配成功后,总线调用驱动的probe函数,设备进入“已绑定”状态。
总线(bus)是设备与驱动之间的匹配中介,例如platform、PCI、USB、I2C、SPI。总线负责枚举设备、维护设备链表和驱动链表,并在新设备或新驱动加入时触发匹配。总线是设备模型中的“红娘”,没有总线,设备与驱动无法自动建立关系。
类(class)是从功能角度对设备的高层抽象,例如net、tty、block、input。类不关心设备挂在哪条总线上,只关心它对外提供什么能力。类的主要作用是让用户空间按功能找到设备,并统一创建/dev节点或sysfs属性。
子系统(subsystem)是更宽泛的顶层组织单位,通常对应/sys/class/、/sys/bus/、/sys/devices/等目录下的一个分支。子系统可以包含总线、类、设备、驱动等多种对象,是内核维护设备层次结构的容器。
二、sysfs、devtmpfs、udev的分工
sysfs是内核导出的虚拟文件系统,挂载在/sys。它把设备模型中的kobject以目录和文件形式呈现,用户可以通过读写属性文件查看或调整设备状态。sysfs是“内核对象视图”,不是设备节点本身。
devtmpfs是内核早期挂载在/dev的虚拟文件系统,由内核在设备注册时自动创建对应的设备节点。它解决了“根文件系统尚未挂载时也需要设备节点”的问题,例如启动阶段需要访问/dev/console、/dev/null。
udev是用户空间的设备管理器,运行在systemd-udevd中。它监听内核通过netlink发送的uevent,根据规则文件在/dev下创建符号链接、修改权限、执行脚本。udev不替代devtmpfs,而是在devtmpfs提供的节点基础上做动态策略管理。
一句话区分:sysfs看“设备模型长什么样”,devtmpfs保证“节点先能用”,udev决定“节点最终叫什么、归谁、触发什么动作”。
三、从设备注册到/dev节点出现的完整链路
以一条platform设备为例,典型流程如下:
- 内核启动或模块加载时,platform总线枚举设备树或ACPI中的设备,创建
struct device并注册到总线设备链表。 - 驱动向总线注册
struct device_driver,总线调用match函数比较设备与驱动的compatible、id_table等字段。 - 匹配成功后,总线调用驱动的probe函数,驱动初始化硬件、申请资源、注册字符设备或网络设备。
- 设备注册时,内核在sysfs中创建对应目录和属性文件,同时通过devtmpfs在
/dev下创建设备节点。 - 内核发送uevent,udev接收后根据
/etc/udev/rules.d/中的规则创建符号链接、设置权限或执行辅助脚本。
# 查看某设备在sysfs中的位置
ls -l /sys/bus/platform/devices/
# 查看设备与驱动的绑定关系
ls -l /sys/bus/platform/drivers/*/
# 查看devtmpfs中的节点
ls -l /dev/ttyS0
# 查看udev规则
udevadm info -a -n /dev/ttyS0
# 监控uevent
udevadm monitor --kernel --udev
四、案例:串口设备从注册到可用
假设SoC的UART控制器在设备树中描述为serial@10000000,compatible为vendor,uart。内核启动时,platform总线根据设备树创建platform_device,串口驱动注册platform_driver。匹配成功后,驱动probe,申请寄存器地址、中断号,注册tty设备。此时sysfs中出现/sys/devices/platform/serial@10000000/,devtmpfs中创建/dev/ttyS0,udev根据规则可能创建/dev/serial/by-id/...符号链接。用户空间程序打开/dev/ttyS0即可通信。
五、常见误区与复盘
| 误区 | 正确理解 |
|---|---|
| sysfs就是/dev | sysfs是内核对象视图,/dev是设备节点目录,两者用途不同。 |
| udev负责创建设备节点 | devtmpfs先创建基础节点,udev在其上做策略管理;无devtmpfs时udev才负责创建。 |
| 设备与驱动直接绑定 | 必须经过总线匹配,总线是设备与驱动之间的必要中介。 |
| 类就是总线 | 类按功能分类,总线按物理/逻辑连接分类,二者维度不同。 |
| 子系统只包含设备 | 子系统可包含总线、类、设备、驱动等多种kobject。 |
排障时建议按“总线是否匹配 → 驱动probe是否成功 → sysfs是否有节点 → devtmpfs是否有设备文件 → udev规则是否生效”的顺序逐层检查,能快速定位设备不可用的原因。
掌握设备、驱动、总线、类、子系统五类对象,以及sysfs、devtmpfs、udev三者的分工,就建立了Linux设备模型的整体地图。后续无论是编写驱动、调试设备树,还是排查/dev节点异常,都可以回到这张地图上定位问题所在。