Uevent是一种在内核空间和用户空间之间通信的机制,主要用于热插拔事件(hotplug)。常用的电量通知、usb拔插通知、耳机拔插通知等都可以使用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);
void *uevent_thread(void* data)
{
int device_fd = -1;
char msg[UEVENT_MSG_LEN+2];
int n;
struct luther_gliethttp luther_gliethttp;
int brun =1;
device_fd = open_luther_gliethttp_socket();
printf("--dxp-- uevent device_fd = %d\n", device_fd);
while(brun){
if((n = recv(device_fd, msg, UEVENT_MSG_LEN, 0)) > 0) {
printf("---- uevent len = %d\n", n);
msg[n] = '\0';
msg[n+1] = '\0';
parse_event(msg, &luther_gliethttp);
}
usleep(1000*10);
}
close(device_fd);
}
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;
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);
}
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);
}
*****************************************************************************************
外部接口只有一个:void *uevent_thread(void* data),这是一个线程,具体uevent解析是在函数parse_event(),当然这里只有打印,可根据具体应用场景加上相应的解析逻辑代码。