Linux kobject_uevent_env

简述

kobject_uevent_env用于Linux下热插拔事件产生时,通知到用户空间的一种方式,uevent是sysfs向用户空间发出的消息。

基本结构

// kobject事件类型
// 源码位置/kernel/msm-3.18/include/linux/kobject.h
enum kobject_action {
	KOBJ_ADD,
	KOBJ_REMOVE,
	KOBJ_CHANGE,
	KOBJ_MOVE,
	KOBJ_ONLINE,
	KOBJ_OFFLINE,
	KOBJ_MAX
};

// 源码位置/kernel/msm-3.18/lib/kobject_uevent.c
/**
 * kobject_uevent - notify userspace by sending an uevent
 *
 * @action: action that is happening
 * @kobj: struct kobject that the action is happening to
 *
 * Returns 0 if kobject_uevent() is completed with success or the
 * corresponding error when it fails.
 */
int kobject_uevent(struct kobject *kobj, enum kobject_action action)

/**
 * kobject_uevent_env - send an uevent with environmental data
 *
 * @action: action that is happening
 * @kobj: struct kobject that the action is happening to
 * @envp_ext: pointer to environmental data
 *
 * Returns 0 if kobject_uevent_env() is completed with success or the
 * corresponding error when it fails.
 */
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp_ext[])

应用实例

内核空间

1.device add:

/*
 * device_add函数中会调用kobject_add,通知应用层有新设备添加
 * &dev->kobj:事件发生位置
 * KOBJ_ADD:事件类型
 */
kobject_uevent(&dev->kobj, KOBJ_ADD);

2.也可在自己的设备驱动里主动调用uevent接口上报消息

/*
 * 这里通过sysfs attribute node向应用层提供接口
 * 当有用户读取该node内容时,即可触发上报动作
 * 上报动作可以直接调用kobject_uevent,事件类型为KOBJ_ADD,事件位置为&dev->kobj
 * 也可调用kobject_uevent_env,第三个参数envp为自定义环境变量,同样会一起上报给应用层
 */
static ssize_t kobject_test_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	unsigned int size = 0;
	// char *envp[2] = {"uevents report test!", NULL};

	// kobject_uevent_env(&dev->kobj, KOBJ_ADD, envp);
	kobject_uevent(&dev->kobj, KOBJ_ADD);

	size += sprintf(buf, "uevents report test!\n");

	return size;
}

用户空间

可参考Android 8.1/system/extras/tests/uevents代码,编译后将uevents推入系统,执行后即可监听来自内核的uevent事件上报。

#include <cutils/uevent.h>
#include <stdio.h>

#define UEVENT_MSG_LEN  1024

int main(int argc, char *argv[])
{
    int device_fd;
    char msg[UEVENT_MSG_LEN+2];
    int n;
    int i;

    device_fd = uevent_open_socket(64*1024, true);
    if(device_fd < 0)
        return -1;

    while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) {
        msg[n] = '\0';
        msg[n+1] = '\0';

        for (i = 0; i < n; i++)
            if (msg[i] == '\0')
                msg[i] = ' ';

        printf("%s\n", msg);
    }

    return 0;
}
// 移除驱动后打印监听到的uevent事件
remove@/devices/soc/soc:test_dev_for_spongebob/test_class/test_node ACTION=remove DEVPATH=/devices/soc/soc:test_dev_for_spongebob/test_class/test_node SUBSYSTEM=test_class MAJOR=222 MINOR=0 DEVNAME=test_node SEQN
UM=4074 
remove@/test_class ACTION=remove DEVPATH=/test_class SUBSYSTEM=class SEQNUM=4075 
remove@/bus/platform/drivers/test_drv_for_spongebob ACTION=remove DEVPATH=/bus/platform/drivers/test_drv_for_spongebob SUBSYSTEM=drivers SEQNUM=4076 
remove@/module/test_driver ACTION=remove DEVPATH=/module/test_driver SUBSYSTEM=module SEQNUM=4077 

// 加载驱动后打印监听到的uevent事件
add@/module/test_driver ACTION=add DEVPATH=/module/test_driver SUBSYSTEM=module SEQNUM=4078 
add@/class/test_class ACTION=add DEVPATH=/class/test_class SUBSYSTEM=class SEQNUM=4079 
add@/devices/soc/soc:test_dev_for_spongebob/test_class/test_node ACTION=add DEVPATH=/devices/soc/soc:test_dev_for_spongebob/test_class/test_node SUBSYSTEM=test_class MAJOR=222 MINOR=0 DEVNAME=test_node SEQNUM=408
0 
add@/bus/platform/drivers/test_drv_for_spongebob ACTION=add DEVPATH=/bus/platform/drivers/test_drv_for_spongebob SUBSYSTEM=drivers SEQNUM=4081

参考链接https://blog.csdn.net/spongebob1912/article/details/108626930

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值