1. 课程导入
在嵌入式Linux、服务器与桌面系统中,设备驱动开发者经常面对一个看似矛盾的现象:内核里明明有成千上万个驱动,用户空间却能用极简的路径访问设备,例如 /dev/ttyS0、/sys/class/net/eth0、/dev/input/event3。这种“内核复杂、用户接口统一”的能力,正是由Linux设备模型(Linux Device Model)提供的。设备模型不是某一个单独的文件,而是一套贯穿内核的对象抽象、注册机制与用户空间视图,它把总线、设备、驱动、类、属性、电源管理等概念组织成可枚举、可匹配、可观察的结构。
本课程聚焦其中的Class(类)与设备节点管理。Class是设备模型面向用户空间的重要出口:它不关心设备挂在哪条总线上,而是按功能归类,例如 net、tty、input、block、sound。设备节点则是用户空间真正打开、读写、控制的入口,通常由 devtmpfs、udev 或 mdev 根据内核事件动态创建。理解Class与节点管理,等于掌握了“驱动如何被看见、设备如何被访问、权限如何被控制”的主线。
本节核心问题:设备模型为什么存在?Class在系统中处于什么位置?设备节点从何而来?后续30章将围绕哪些能力展开?
一、Linux设备模型的核心抽象
Linux设备模型用 kobject、kset、device、device_driver、bus_type、class 等结构描述内核对象及其关系。可以把它理解为一张动态维护的“设备关系网”:
- kobject:最基础的对象引用计数与sysfs目录表示,是设备模型的地基。
- bus_type:总线类型,负责设备与驱动的匹配,如
platform、i2c、spi、usb、pci。 - device:具体设备实例,挂接在总线上,拥有资源、属性和生命周期。
- device_driver:驱动实现,通过
probe与设备绑定,通过remove解绑。 - class:按功能划分的设备集合,向用户空间提供统一视图,如
/sys/class/net。 - device node:用户空间设备文件,如
/dev/video0,由设备号与驱动关联。
这些对象最终都映射到 sysfs 中。sysfs不是普通文件系统,而是内核对象关系的实时投影。用户执行 ls /sys/class 看到的目录,正是Class抽象的直接体现。
二、Class与节点管理在系统中的位置
从数据流看,设备模型位于“硬件/总线”与“用户空间”之间。硬件被总线枚举后生成device;驱动匹配后注册class与属性;内核通过uevent通知用户空间;用户空间的udev/mdev根据uevent创建设备节点并设置权限。整个过程可以用下面的关系图表示:
图中可见,Class并不直接创建设备节点,而是提供“功能分类视图”和uevent信息。真正让 /dev 出现节点的是用户空间设备管理器。因此,Class与节点管理是“内核抽象”与“用户空间落地”之间的桥梁。
三、方法流程:一次设备注册到节点生成
以平台设备为例,典型流程如下:
- 设备树或板级代码描述硬件,内核生成
platform_device。 - 驱动注册
platform_driver,总线匹配成功后调用probe。 - 驱动申请设备号,注册
cdev或class_create/device_create。 - 内核在sysfs中生成
/sys/class/xxx/yyy,并发出uevent。 - udev/mdev接收uevent,读取
dev属性中的主次设备号。 - 在
/dev下创建节点,设置权限、属主和符号链接。
# 观察 class 与设备节点
ls -l /sys/class/net/
ls -l /dev/ttyS0
cat /sys/class/tty/ttyS0/dev
# 输出示例:4:64
# 查看 uevent 内容
cat /sys/class/net/eth0/uevent
# 输出示例:
# INTERFACE=eth0
# IFINDEX=2
这段命令展示了Class视图、设备号与uevent之间的对应关系。设备号 4:64 是内核内部标识,/dev/ttyS0 是用户空间入口,二者通过设备节点管理绑定。
四、案例场景:串口设备从注册到可用
假设SoC有一个UART控制器,内核启动后出现 /dev/ttyS0。背后发生的事包括:串口驱动注册 tty_driver,创建 tty_class,调用 device_create 生成 /sys/class/tty/ttyS0,并发出uevent。udev根据规则创建 /dev/ttyS0,权限通常为 crw-rw---- root dialout。应用打开该节点即可收发数据。
如果节点没有出现,排查顺序通常是:驱动是否probe成功、class是否注册、uevent是否发出、udev/mdev是否运行、规则是否匹配、权限是否被覆盖。这个排查链条正是本课程后续要反复训练的能力。
五、常见误区与复盘
| 误区 | 实际情况 | 正确做法 |
|---|---|---|
| Class就是设备节点 | Class是sysfs功能视图,节点在/dev | 分别查看 /sys/class 与 /dev |
| 设备号无关紧要 | 主次设备号决定内核如何找到驱动 | 用 cat /sys/class/.../dev 核对 |
| udev规则一定生效 | 规则顺序、匹配条件、权限都会影响结果 | 用 udevadm test 验证 |
| 节点创建后权限不会变 | 后续规则或服务可能覆盖权限 | 检查规则优先级与默认权限 |
学习建议:每学一个概念,都在真实系统中找对应路径。看到 /sys/class 想Class,看到 /dev 想节点,看到 uevent 想事件传递。三者联动,设备模型就不再抽象。
六、整体知识框架与学习目标
本课程后续将围绕五条主线展开:设备模型基础对象与sysfs、Class机制与class_create/device_create、设备号与cdev、uevent与用户空间事件、udev/mdev规则与节点权限管理。最终目标是能够独立完成驱动侧Class注册、用户空间节点生成、权限配置与故障排查。
- 理解kobject、kset、device、driver、bus、class之间的关系。
- 掌握Class的注册、注销与sysfs属性组织。
- 掌握设备号分配、cdev注册与设备节点生成流程。
- 能编写和调试udev/mdev规则,控制节点权限与命名。
- 能定位“驱动正常但节点缺失”“权限错误”“节点名不符”等典型问题。
设备模型是Linux驱动工程的骨架,Class与节点管理是骨架上的关节。掌握它们,才能在复杂系统中让设备“被内核识别、被用户空间看见、被应用正确访问”。