Linux kobject_uevent_env通知应用层事件方法

Linux内核层:

kset_create_and_add //内核创建和注册kset

kobject_init //kobject初始化

kobject_add //初始化完成的 kobject 添加到内核中

kobject_uevent_env(obj, action, env) //上报给应用层

kobject_uevent默认会发送”ACTION=xxx”,”DEVPATH=xxx”,”SUBSYSTEM=xxx”这三个uevent环境变量,其中env可用如下方法赋值。

 char*env[] = {NULL,NULL};
 strcpy(buf,"USBEVENT=xxx_notify");
 env[0] = buf;
  

其中action为enum kobject_action中的枚举值,在内核kobject.h中有定义

enum kobject_action {
        KOBJ_ADD,
        KOBJ_REMOVE,
        KOBJ_CHANGE,
        KOBJ_MOVE,
        KOBJ_ONLINE,
        KOBJ_OFFLINE,
        KOBJ_BIND,
        KOBJ_UNBIND,
};

应用层接收uevent消息代码示例:

#include <stdio.h>

#include <errno.h>
#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#include <linux/netlink.h>

#define UEVENT_MSG_LEN  1024
int uevent_open_socket(int buf_sz, bool passcred)
{
    struct sockaddr_nl addr;
    int on = passcred;
    int s;

    memset(&addr, 0, sizeof(addr));
    addr.nl_family = AF_NETLINK;
    addr.nl_pid = getpid();
    addr.nl_groups = 0xffffffff;

    s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
    if(s < 0)
        return -1;

    setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &buf_sz, sizeof(buf_sz));
    setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));

    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0)
    {
        close(s);
        return -1;
    }

    return s;
}


ssize_t uevent_kernel_multicast_uid_recv(int socket, void *buffer,
        size_t length, uid_t *user)
{
    struct iovec iov = { buffer, length };
    struct sockaddr_nl addr;
        int len = sizeof(struct ucred);
    char control[CMSG_SPACE(len)];
    struct msghdr hdr =
    {
        &addr,
        sizeof(addr),
        &iov,
        1,
        control,
        sizeof(control),
        0,
    };

    *user = -1;
    ssize_t n = recvmsg(socket, &hdr, 0);
    if (n <= 0)
    {
        return n;
    }

    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&hdr);
    if (cmsg == NULL || cmsg->cmsg_type != 0x02) //SCM_CREDENTIALS = 0x02 //03_14
    {
        /* ignoring netlink message with no sender credentials */
        goto out;
    }

    struct ucred *cred = (struct ucred *)CMSG_DATA(cmsg);
    *user = cred->uid;
    if (cred->uid != 0)
    {
        /* ignoring netlink message from non-root user */
        goto out;
    }

    if (addr.nl_groups == 0 || addr.nl_pid != 0)
    {
        /* ignoring non-kernel or unicast netlink message */
        goto out;
    }

    return n;

out:
    /* clear residual potentially malicious data */
    bzero(buffer, length);
    errno = EIO;
    return -1;
}

ssize_t uevent_kernel_multicast_recv(int socket, void *buffer, size_t length)
{
    uid_t user = -1;
    return uevent_kernel_multicast_uid_recv(socket, buffer, length, &user);
}

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;
}
 

编译成可执行应用程序后,运行,然后Linux底层驱动进行事件上报:

应用层收到信息如下:

online@/xxx/xxx_notify ACTION=online DEVPATH=/xxx/xxx_notify SUBSYSTEM=xxx USBEVENT=xxx_notify SEQNUM=633

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: kobject_uevent_env是一个内核函数,用于发送内核事件通知。它可以在内核中创建一个kobject对象,并将其与一个事件关联起来,然后将事件发送到用户空间。这个函数可以用于驱动程序中,以通知用户空间有关设备状态的变化。 ### 回答2: kobject_uevent_env是一个内核级别的函数,用于通知用户空间的udev守护进程设备的状态变化。在Linux内核中,每个设备都被抽象成一个kobject结构体。当设备的状态发生改变(如插入或移除设备),内核调用kobject_uevent_env函数生成一个事件消息,该消息包含了设备发生变化的相关信息。这个事件消息将被传递给udev守护进程,从而触发相应的设备操作。 kobject_uevent_env函数的原型如下: ``` int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char **envp); ``` 其中: - kobj:要发送事件消息的设备的kobject结构体。 - action:设备发生的操作,如添加(KOBJ_ADD)或删除(KOBJ_REMOVE)。 - envp:指向要发送给udev的事件消息的缓冲区指针。 kobject_uevent_env函数也支持环境变量的传递。在发送事件消息时,可以将一些自定义的环境变量随消息一起传递给udev守护进程,以便udev能够根据这些环境变量执行相应的操作。 通常来说,kobject_uevent_env函数是由内核模块中的设备驱动程序所调用的。设备驱动程序在操作设备时,会调用kobject_uevent_env函数向用户空间的udev守护进程发送事件消息,通知它设备的状态变化。在用户空间,udev守护进程将根据这些事件消息执行相应的设备管理操作。 ### 回答3: kobject_uevent_env 是一个内核函数,它用于通知用户空间有关内核对象的事件通知是通过用户空间的 uevent 机制实现的,这个机制允许内核将事件通知到用户空间的程序中。kobject_uevent_env 函数将事件的环境信息作为参数传递给 uevent 机制,所以用户空间程序可以根据环境信息来处理事件。 kobject_uevent_env 函数的参数是一个指向 kobject 结构体的指针和一个环境变量数组。kobject 结构体表示内核对象,环境变量数组包含事件相关的环境变量。环境变量数组的每个元素都是一个字符串,格式为 "key=value"。其中,key 表示环境变量的名称,value 表示环境变量的值。 kobject_uevent_env 函数的调用者通常是内核驱动程序,当驱动程序中的某个内核对象发生事件时,驱动程序会调用 kobject_uevent_env 函数来通知用户空间。用户空间程序可以使用 libudev 库来监视 uevent 事件并相应地处理。 总之,kobject_uevent_env 是内核中实现 uevent 机制的重要函数之一,它允许内核将事件通知到用户空间,并传递事件相关的环境信息。通过 uevent 机制,用户空间程序可以监视内核对象的事件并做出相应的处理,这对于管理设备和驱动程序非常重要。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

a2591748032-随心所记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值