内核中的uevent
uevent(user space event) 是 内核 提供的一个机制,属于 kobject 中的一个技术实现,代码在lib/kobject_uevent.c
Uevent是Kobject的一部分,用于在Kobject状态发生改变时,通知用户空间进程
改变是什么
ADD/REMOVE,Kobject(或上层数据结构)的添加/移除事件。
ONLINE/OFFLINE,Kobject(或上层数据结构)的上线/下线事件,其实是是否使能。
CHANGE,Kobject(或上层数据结构)的状态或者内容发生改变。
MOVE,Kobject(或上层数据结构)更改名称或者更改Parent(意味着在sysfs中更改了目录结构)。
CHANGE,如果设备驱动需要上报的事件不再上面事件的范围内,或者是自定义的事件,可以使用该event,并携带相应的参数。
1.内核如何向用户空间通信(上报uevent事件)
lib/kobject_uevent.c
kobject_uevent
kobject_uevent_env
2.用户空间控制内核给用户空间通信
sysfs 下的很多 kobject 下都有 uevent 属性,它主要用于内核与udev/mdev或其他用户空间进程之间的一个通信接口,将sysfs挂载到/sys, uevent属性就变为了可见的文件
内核将 uevent 机制暴露给了用户空间(对应/sys下的uevent文件) , 让用户空间控制内核给用户空间通信
在每个注册的device文件夹下会生成一个uevent属性文件
drivers/base/core.c
uevent_store
uevent_show
static DEVICE_ATTR_RW(uevent);
/sys下的uevent文件支持写入的参数有 "add","remove","change","move","online","offline"
写入 "add",这样内核就会调用 uevent_store -> kobject_uevent
A.通信中的信息内容
???
内核uevent的消费者
1.内核如何向用户空间通信 的消费者
主要用于设备驱动模型中热插拔设备或设备状态变化时。
该机制通常是用来支持热拔插设备的,
device_create
device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
device_register(dev);
device_add(dev);
kobject_uevent(&dev->kobj, KOBJ_ADD);
kobject_uevent_env(kobj, action, NULL);
2.用户空间控制内核给用户空间通信 的消费者
可用于实现手动触发hotplug(手动触发hotplug就是coldplug)
可用于 udevmonitor 通过内核向 udevd (udev 后台程序)发送消息
也可用于检查设备本身所支持的 netlink 消息上的环境变量
也可用于开发人员调试 udev 规则文件,udevtrigger 这个调试工具本身就是以写各设备的 uevent 属性文件实现的。
内核uevent的性能
无论是usermodehelper还是netlink的方式,uevent对系统性能是有影响的。
特别是netlink的方式,上报的event会通知到所有的用户进程,所以还是少用为妙
内核uevent的底层实现
当消费者调用kobject_uevent上报事件时,kobject_uevent会根据配置不同,主要有两个代码路径
一种是通过kmod模块,直接调用用户空间的可执行文件;
一种是通过netlink通信机制,将事件从内核空间传递给用户空间
Uevent模块通过Kmod上报Uevent时,会通过call_usermodehelper函数
调用用户空间的可执行文件(或者脚本,简称uevent helper,目前2021年1月18日 一般为mdev)处理该event。
kobject_uevent(&dev->kobj, KOBJ_ADD);
kobject_uevent_env(kobj, action, NULL);
const char *action_string = kobject_actions[action];
add_uevent_var(env, "ACTION=%s", action_string);
add_uevent_var(env, "DEVPATH=%s", devpath);
add_uevent_var(env, "SUBSYSTEM=%s", subsystem);
init_uevent_argv
call_usermodehelper_setup
call_usermodehelper_exec
从上面的调用关系可以看出,最终内核会调用/proc/sys/kernel/hotplug 中指定的
程序(一般会配置为/sbin/mdev),并且使用该程序的环境变量
Netlink套接字
是用以实现用户进程与内核进程通信的一种特殊的进程间通信(IPC)
也是网络应用程序与内核通信的最常用的接口。
是一种特殊的 socket
是 Linux 所特有的,类似于 BSD 中的AF_ROUTE 但又远比它的功能强大
是一种在内核与用户应用间进行双向数据传输的非常好的方式
Netlink套接字的消费者
目前在Linux 内核中使用netlink 进行应用与内核通信的应用很多
Netlink套接字实例
路由 daemon(NETLINK_ROUTE),
用户态 socket 协议(NETLINK_USERSOCK),
防火墙(NETLINK_FIREWALL),
netfilter 子系统(NETLINK_NETFILTER),
内核事件向用户态通知(NETLINK_KOBJECT_UEVENT),
通用 netlink(NETLINK_GENERIC)
Netlink使用实例
用户态
应用使用标准的 socket API 就可以使用 netlink 提供的强大功能,
内核态
需要使用专门的内核 API 来使用 netlink。
Netlink特点
1.netlink使用简单,只需要在include/linux/netlink.h中增加一个新类型的 netlink 协议定义即可,(如 #define NETLINK_TEST 20 )
然后,内核和用户态应用就可以立即通过 socket API 使用该 netlink 协议类型进行数据交换);
2.netlink是一种异步通信机制,在内核与用户态应用之间传递的消息保存在socket缓存队列中
发送消息只是把消息保存在接收者的socket的接收队列,而不需要等待接收者收到消息;
3.使用 netlink 的内核部分可以采用模块的方式实现
使用 netlink 的应用部分和内核部分没有编译时依赖;
4.netlink 支持多播,内核模块或应用可以把消息多播给一个netlink组
属于该neilink 组的任何内核模块或应用都能接收到该消息
内核事件向用户态的通知机制就使用了这一特性
5.内核可以使用 netlink 首先发起会话
对应内核uevent的用户空间实现
1. mdev怎么处理coldplug的
只要是用户空间处理创建设备文件,就会有冷插拔的问题
在启动脚本rcS中会有这样一句命令/sbin/mdev -s
1. 扫描/sys目录里所有的uevent属性文件,向其写入"add”命令,触发uevent事件
2. 内核调用 call_usermodehelper (argv[0], argv, envp, 0); fork mdev
3. mdev 根据 参数 创建设备文件
2. mdev 怎么处理hotplug
1. 内核创建device,同时触发uevent事件
2. 内核调用 call_usermodehelper (argv[0], argv, envp, 0); fork mdev
3. mdev 根据 参数 创建设备文件
A.mdev的函数调用路径
int mdev_main(int argc UNUSED_PARAM, char **argv)
xchdir("/dev");
if (argv[1] && strcmp(argv[1], "-s") == 0) {
putenv((char*)"ACTION=add");
if (access("/sys/class/block", F_OK) != 0) {
recursive_action("/sys/block",
ACTION_RECURSE | ACTION_FOLLOWLINKS | ACTION_QUIET,
fileAction, dirAction, temp, 0);
}
recursive_action("/sys/class",
ACTION_RECURSE | ACTION_FOLLOWLINKS,
fileAction, dirAction, temp, 0);
}else{
env_devname = getenv("DEVNAME");
G.subsystem = getenv("SUBSYSTEM");
action = getenv("ACTION");
env_devpath = getenv("DEVPATH");
snprintf(temp, PATH_MAX, "/sys%s", env_devpath);
make_device(env_devname, temp, op);
}
是 netlink 对应的用户空间进程实现
具体请查看 https://blog.csdn.net/u011011827/article/details/112741721