浅析u盘等热插拔uevent事件用户空间截获方法和具体实现

 

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <linux/netlink.h>

#define UEVENT_MSG_LEN 4096
struct luther_gliethttp {
    const char *action;
    const char *path;
    const char *subsystem;
    const char *firmware;
    int major;
    int minor;
};
static int open_luther_gliethttp_socket(void);
static void parse_event(const char *msg, struct luther_gliethttp *luther_gliethttp);

int main(int argc, char* argv[])
{
    int device_fd = -1;
    char msg[UEVENT_MSG_LEN+2];
    int n;
    
    device_fd = open_luther_gliethttp_socket();
    printf("device_fd = %d/n", device_fd);

    do {
        while((n = recv(device_fd, msg, UEVENT_MSG_LEN, 0)) > 0) {
            struct luther_gliethttp luther_gliethttp;

            if(n == UEVENT_MSG_LEN) /* overflow -- discard */
                continue;

            msg[n] = '/0';
            msg[n+1] = '/0';

            parse_event(msg, &luther_gliethttp);
        }
    } while(1);
}

static int open_luther_gliethttp_socket(void)
{
    struct sockaddr_nl addr;
    int sz = 64*1024;
    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, &sz, sizeof(sz));

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

    return s;
}

static void parse_event(const char *msg, struct luther_gliethttp *luther_gliethttp)
{
    luther_gliethttp->action = "";
    luther_gliethttp->path = "";
    luther_gliethttp->subsystem = "";
    luther_gliethttp->firmware = "";
    luther_gliethttp->major = -1;
    luther_gliethttp->minor = -1;

    /* currently ignoring SEQNUM */
    printf("========================================================/n");
    while (*msg) {

        printf("%s/n", msg);

        if (!strncmp(msg, "ACTION=", 7)) {
            msg += 7;
            luther_gliethttp->action = msg;
        } else if (!strncmp(msg, "DEVPATH=", 8)) {
            msg += 8;
            luther_gliethttp->path = msg;
        } else if (!strncmp(msg, "SUBSYSTEM=", 10)) {
            msg += 10;
            luther_gliethttp->subsystem = msg;
        } else if (!strncmp(msg, "FIRMWARE=", 9)) {
            msg += 9;
            luther_gliethttp->firmware = msg;
        } else if (!strncmp(msg, "MAJOR=", 6)) {
            msg += 6;
            luther_gliethttp->major = atoi(msg);
        } else if (!strncmp(msg, "MINOR=", 6)) {
            msg += 6;
            luther_gliethttp->minor = atoi(msg);
        }

        /* advance to after the next /0 */
        while(*msg++)
            ;
    }

    printf("event { '%s', '%s', '%s', '%s', %d, %d }/n",
                    luther_gliethttp->action, luther_gliethttp->path,luther_gliethttp->subsystem,
                    luther_gliethttp->firmware, luther_gliethttp->major,luther_gliethttp->minor);
}

 

 

命令的话可以使用udevmonitor

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux操作系统是一种开放源代码的操作系统,其用户空间可以通过使用netlink来监听uevent(用户事件)。netlink是一种用于内核和用户空间之间进行通信的机制,可以实现内核对用户空间事件的广播。 在Linux中,用户空间使用netlink来监听uevent的主要目的是为了获取与设备相关的信息和事件通知。通过监听uevent,用户空间可以获得设备的插拔状态、设备的属性变化、系统的电源管理事件等等。 使用netlink监听uevent的过程一般包括以下几个步骤: 1. 创建与内核通信的socket用户空间需要创建一个socket,并使用socket系统调用将其与netlink协议相关联。 2. 绑定socketuevent通信组:调用bind系统调用将socket绑定到uevent通信组,以便接收与设备相关的事件通知。 3. 接收并处理uevent:使用recv系统调用从socket中接收uevent消息,并在用户空间中对其进行处理。用户空间可以根据收到的uevent消息来进行相应的操作,例如更新设备列表、触发相关动作等。 需要注意的是,使用netlink监听uevent需要具备相应的权限。一般情况下,只有具有管理员权限的用户或特定的用户组才能够进行这类操作。 在Linux中,用户空间使用netlink监听uevent是实现设备管理和与设备相关的操作的重要手段之一。它可以使用户空间获取到内核层面的设备信息,并根据这些信息做出相应的响应和决策。这对于开发系统工具、设备驱动程序以及一些需要实时监控设备状态的应用程序非常有用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值