ueventd和dev节点
一、核心结论(先看结论)
/dev下的设备节点是由 用户空间进程ueventd(Android 的简化版udevd)创建的。- 设备节点的创建是因为 内核在设备注册时(device_register)通过
kobject_uevent()发送了 uevent 消息。 ueventd监听这些来自内核的 netlink 消息(NETLINK_KOBJECT_UEVENT),解析后根据规则文件(ueventd.rc等)创建/dev设备节点。- 创建设备节点的本质是调用
mknod()系统调用,并设置对应的权限、属主和 SELinux 上下文。
二、内核层(发送 uevent)
当驱动在内核中注册一个设备时,会调用:
device_register()
└── kobject_uevent(&dev->kobj, KOBJ_ADD);
这会产生一个 uevent 消息,比如:
ACTION=add
DEVNAME=sda
DEVPATH=/devices/platform/soc/.../block/sda
SUBSYSTEM=block
MAJOR=8
MINOR=0
然后这个消息通过 netlink socket (NETLINK_KOBJECT_UEVENT) 广播到用户空间。
三、用户空间:ueventd 的作用
Android 系统启动早期,会启动 ueventd 进程(由 init 通过 init.rc 启动):
service ueventd /system/bin/ueventd
class core
critical
ueventd 的主要逻辑在 system/core/init/ueventd_main.cpp 和 system/core/init/uevent_listener.cpp。
其核心行为是:
- 打开
NETLINK_KOBJECT_UEVENTsocket; - 不断
recvmsg()等待内核发来的 uevent; - 解析出关键字段(
ACTION、DEVNAME、MAJOR、MINOR等); - 根据
ueventd.rc或ueventd.<hardware>.rc的规则决定:/dev/<name>节点路径;- 节点权限(mode);
- 属主、属组;
- 是否需要符号链接(如
/dev/block/platform/soc/...)。
- 调用
make_device()创建节点:
int make_device(const char* path, int block, int major, int minor, mode_t perm, uid_t uid, gid_t gid) {
dev_t dev = makedev(major, minor);
int flags = block ? S_IFBLK : S_IFCHR;
mknod(path, flags | perm, dev);
chown(path, uid, gid);
}
四、设备节点的创建路径
举例说明:
当内核注册一个 USB 串口设备 /dev/ttyUSB0 时,内核会发出 uevent:
ACTION=add
DEVNAME=ttyUSB0
DEVTYPE=tty
MAJOR=188
MINOR=0
SUBSYSTEM=tty
ueventd 收到后:
-
查找
ueventd.rc是否有匹配规则:/dev/ttyUSB* 0660 root uucp -
没有匹配则使用默认权限;
-
执行:
mknod /dev/ttyUSB0 c 188 0 chmod 0660 /dev/ttyUSB0 chown root:uucp /dev/ttyUSB0
最终 /dev/ttyUSB0 节点就出现在文件系统中了。
五、配置文件:ueventd.rc 与 ueventd..rc
这两个文件指定了节点的默认权限、属主和符号链接规则。示例:
/dev/null 0666 root root
/dev/tty[0-9]* 0660 root shell
/dev/usb/lp* 0660 root shell
/dev/block/mmcblk[0-9]* 0660 root disk
/dev/bus/usb/* 0660 root usb
设备匹配规则支持通配符。
六、ueventd 与 init 的区别
| 项目 | init | ueventd |
|---|---|---|
| 功能 | 管理系统服务、挂载、属性设置等 | 管理 /dev 下的设备节点 |
| 事件来源 | init.rc 配置 | 内核 kobject_uevent |
| 工作时机 | 启动整个系统 | 启动早期即运行 |
| 通信机制 | 属性系统 + socket | netlink: NETLINK_KOBJECT_UEVENT |
七、总结流程图
内核驱动注册设备
↓
kobject_uevent(KOBJ_ADD)
↓
通过 netlink 发送消息到用户空间
↓
ueventd 监听 NETLINK_KOBJECT_UEVENT
↓
解析消息,查找匹配规则
↓
调用 mknod() 创建 /dev 节点
↓
设置权限 / 属主 / SELinux 标签
八、扩展:Android 和传统 Linux 的区别
- 传统 Linux 用
udevd(systemd-udevd)来处理设备节点; - Android 由于追求轻量化和早期可用性,用的是简化版
ueventd; udevd会执行复杂的规则文件(如/lib/udev/rules.d/*),而ueventd只支持简单匹配


浙公网安备 33010602011771号