2. 设备节点基础:Linux 设备文件系统与节点创建机制
在 Linux 系统中,设备节点是用户空间与内核驱动交互的“门把手”。理解设备文件系统(devfs/sysfs)、主次设备号以及节点创建机制,是掌握 HAL 层驱动开发的第一步。本章将系统梳理这些基础概念,并通过结构图与表格帮助建立清晰的认知模型。
2.1 设备文件系统:devfs 与 sysfs
Linux 通过虚拟文件系统将内核中的设备信息暴露给用户空间。历史上先后出现了 devfs 和 sysfs 两种主要机制,它们的设计理念与用途有显著差异。
| 特性 | devfs(设备文件系统) | sysfs(系统文件系统) |
|---|---|---|
| 挂载点 | /dev | /sys |
| 主要用途 | 提供设备节点文件,用于 open/read/write | 导出内核对象、驱动、设备拓扑与属性 |
| 设备节点管理 | 内核自动创建/删除设备节点 | 不直接创建设备节点,提供设备信息 |
| 用户空间交互 | 通过文件 I/O 操作设备 | 通过读写属性文件查询/配置设备 |
| 生命周期 | Linux 2.6 早期,已被 udev 取代 | 从 Linux 2.6 至今,持续使用 |
| 命名策略 | 内核硬编码,不灵活 | 基于 kobject 层次结构,动态生成 |
实践要点: 在 HAL 层开发中,
/sys 用于发现设备拓扑和读取属性(如设备号、供应商 ID),而 /dev 下的节点才是实际进行数据读写的入口。两者协同工作,缺一不可。
2.2 主设备号与次设备号
每个设备节点在 Linux 内核中由一对整数唯一标识:主设备号(Major Number) 和 次设备号(Minor Number)。它们是驱动与设备节点绑定的核心纽带。
- 主设备号: 标识设备对应的驱动程序。内核通过主设备号在全局设备表(chrdevs / blkdevs)中找到对应的 file_operations 结构体。
- 次设备号: 由驱动内部解释,通常用于区分同一驱动控制下的多个物理或逻辑设备(如多个串口、多个分区)。
关键理解: 主设备号是“驱动索引”,次设备号是“设备实例索引”。一个驱动可以管理多个次设备,但一个次设备只能属于一个主设备号。
| 概念 | 范围(典型) | 分配方式 | 查看命令 |
|---|---|---|---|
| 主设备号 | 1 ~ 511(字符设备) | 静态分配(Documentation/devices.txt)或动态分配(alloc_chrdev_region) | cat /proc/devices |
| 次设备号 | 0 ~ 1048575(20 位) | 驱动开发者自定义,通常从 0 开始顺序编号 | ls -l /dev(显示主,次) |
2.3 设备节点创建机制:mknod 与 udev
设备节点本质上是存储在磁盘上的一个特殊文件,包含设备类型(字符/块)、主设备号和次设备号。创建节点有两种典型方式:手动创建(mknod)和自动创建(udev)。
2.3.1 手动创建:mknod 命令
mknod 是最原始的设备节点创建工具,在嵌入式系统早期或 initramfs 环境中仍会使用。其语法为:
mknod /dev/mydevice [c|b] major minor
c:字符设备b:块设备major:主设备号minor:次设备号
注意: 手动 mknod 要求开发者预先知道主次设备号,且节点不会随设备热插拔自动消失。在动态设备越来越多的今天,这种方式已不推荐用于产品环境。
2.3.2 自动创建:udev 机制
udev 是 Linux 用户空间设备管理器,它监听内核通过 uevent 发送的设备事件,并根据规则自动在 /dev 下创建或删除设备节点。udev 的工作流程如下:
- 内核事件触发: 驱动注册设备时,内核通过 kobject_uevent() 发送 ADD 事件。
- udev 守护进程接收: udevd 通过 netlink socket 接收 uevent。
- 规则匹配: udev 根据
/etc/udev/rules.d/下的规则文件匹配设备属性(如 vendor、product、kernel 名称)。 - 节点创建: 匹配成功后,udev 调用 mknod 创建节点,并可执行自定义脚本(如设置权限、创建符号链接)。
2.4 设备节点访问控制基础
在 HAL 层开发中,设备节点的访问权限直接决定了用户空间程序能否成功打开设备。权限控制分为三个层面:
| 控制层面 | 机制 | 典型配置 |
|---|---|---|
| 文件权限 | 标准的 UNIX 文件权限(rwx) | crw-rw---- 1 root dialout 4, 64 ... |
| udev 规则 | 通过 MODE、OWNER、GROUP 字段控制 | MODE="0660", GROUP="dialout" |
| Security Modules | SELinux / AppArmor 强制访问控制 | 针对 HAL 守护进程的 domain 策略 |
HAL 层实践建议: 在嵌入式系统中,通常通过 udev 规则将设备节点权限设置为
0660,并将 HAL 守护进程加入对应的用户组(如 dialout、gpio),避免使用 0777 权限带来的安全风险。
2.5 本章小结
- devfs 是早期的设备节点管理方式,已被 sysfs + udev 取代。
- 主设备号 标识驱动,次设备号 标识设备实例,两者共同构成设备节点的“身份证”。
- mknod 用于手动创建节点,适合调试和最小系统;udev 是生产环境的标准方案,支持热插拔和灵活规则配置。
- 设备节点的访问权限控制是 HAL 层安全的基础,应遵循最小权限原则。