了解 热插拔-kset_uevent_ops知识点
文章目录
前言
前面了解了驱动-热插拔-内核发送事件到用户空间-uevent 其实就是uevent 事件传递流程的过程,通过分析 kobject_uevent 函数API,了解了整个流程。 这里再次分析一下流程中 uevent_ops 结构体。
参考资料
驱动-热插拔-内核发送事件到用户空间-uevent
热插拔
内核发送事件到用户空间
完善kset_uevent_ops结构体
一、 uevent_ops 知识点
为什么在uevent事件中需要了解这个结构体
在 驱动-热插拔-内核发送事件到用户空间-uevent 篇中 我们分析了内核空间发送事件到用户空间带源码流程, 也初步分析了 uevent_ops 相关知识点,如下: 可以再次温习一下知识点。

继续看看发送事件源码 kobject_uevent 部分片段:
- 如果存在
uevent_ops且有filter方法,就会过滤一次filter(kobj) - 如果
uevent_ops存在且有name,则影响子系统name


我们就是为了分析和了解uvent_ops 的实际应用和关联知识点
uevent_ops 结构体详情
struct kset_uevent_ops 是一个包含函数指针的结构体,它定义了kset(内核对象集合)如何控制和处理其成员 kobject 发出的 uevent。当 kobject 的状态发生变化(如添加、移除、绑定驱动等)时,内核会生成 uevent 来通知用户空间(例如 udev)。这个结构体提供了三个钩子函数(hook functions),允许 kset 的所有者“拦截”并“定制”这一过程。
其定义通常位于 include/linux/kobject.h 中:
struct kset_uevent_ops {
int (* const filter)(const struct kobject *kobj);
const char *(* const name)(const struct kobject *kobj);
int (* const uevent)(const struct kobject *kobj, struct kobj_uevent_env *env);
};
下面对每个成员进行详细解释:
filter - 事件过滤器
原型: int (*filter)(const struct kobject *kobj);
作用: 决定是否允许为指定的 kobject 生成 uevent。
应用场景: 用于过滤掉不需要通知用户空间的 kobject。例如,一个虚拟的或内部的 kobject,其状态变化对用户空间没有意义,就可以在此函数中返回 0 将其过滤掉。
name - 重命名子系统
原型: const char *(*name)(const struct kobject *kobj);
作用: 覆盖 uevent 中默认的 SUBSYSTEM 属性值。
返回值:
- 字符串指针: 返回一个字符串,该字符串将作为 uevent 的 SUBSYSTEM= 字段的值。
- NULL: 使用 kobject 所属的 kset 的名称作为默认的 SUBSYSTEM 值。
应用场景: 用于实现子系统的“重命名”或统一管理。例如,多个不同的 kset 可能希望它们发出的 uevent 在用户空间看来都来自同一个子系统,就可以通过这个钩子函数返回相同的名字。
uevent - 事件增强器
原型: int (*uevent)(const struct kobject *kobj, struct kobj_uevent_env *env);
作用: 在 uevent 被发送到用户空间之前,向其添加额外的环境变量。这是最常用、最强大的一个钩子函数。
参数:
kobj: 触发事件的kobject。env: 指向struct kobj_uevent_env的指针,该结构体包含了当前已准备的环境变量列表(如ACTION,DEVPATH,SUBSYSTEM等),并提供了添加新变量的API(如add_uevent_var)。
应用场景: 添加任何驱动或子系统需要的自定义信息。这是设备模型向 udev 传递关键信息的主要方式。例如:
- 添加设备厂商ID、产品ID:
add_uevent_var(env, "PRODUCT=%x/%x/%x", idVendor, idProduct, bcdDevice); - 添加设备序列号:
add_uevent_var(env, "SERIAL=%s", serial); - 添加设备类型标志。
uevent_ops 在结构体中的实际应用
内核中 uevent 的发送核心函数是 kobject_uevent(或它的高级封装 kobject_uevent_env)。其基本流程如下:
事件触发: 某个内核代码调用 kobject_add、kobject_del 或设备绑定驱动等,导致需要发送 uevent。
查找 kset 和 ops: 内核向上遍历 kobject 的层次结构,找到其所属的 kset,并获取该 kset 的 uevent_ops。
调用 filter: 如果 kset 定义了 filter 操作,则调用它。如果 filter 返回 0,流程终止,uevent 不会被发送。
调用 name: 如果 kset 定义了 name 操作,则调用它来获取子系统名称;否则,使用 kset 的名称。
准备基础环境变量: 内核初始化 kobj_uevent_env 结构,添加一些标准变量,如:

最低0.47元/天 解锁文章
2211

被折叠的 条评论
为什么被折叠?



