Android(安卓):Kernel Uevent发送(热插拔)事件到用户空间
16lz
2021-01-24
Android :Kernel Uevent发送(热插拔)事件到用户空间
一、Uevent是一种在内核空间和用户空间之间通信的机制,主要用于热插拔事件(hotplug),比如USB和HDMI拔插事件。
二、uevent事件
uevent事件在include/linux/kobject.h中有的定义,kobject对应的动作可分为以下几种:
三、发送事件方法
内核中通过kobject_uevent_env函数将事件发送到用户空间
四、实例测试
1、kernel驱动文件kobject_uevent_env.c
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct device *dev = NULL;char * mesg[2];static ssize_t send_message(struct device *dev,struct device_attribute *attr, const char *buf, size_t count){int ret = 0;char s_buf[100]={0};char *event_string = "HOTPLUG=1"; mesg[0] =s_buf; //mesg[0]= "HOTPLUG=1"; mesg[1] = NULL;//strcat(s_buf, "kobject_uevent_env hello");strcat(s_buf, buf);printk(KERN_WARNING "received message buf=%s s_buf=%s count=%d\n",buf,s_buf,count); kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, mesg); return count;}static DEVICE_ATTR(m_point, S_IRUGO|S_IWUSR, NULL, send_message);static const struct attribute *kobject_event_attr[] = { &dev_attr_m_point.attr, NULL,};static const struct attribute_group kobject_event_attr_group = { .attrs = (struct attribute **) kobject_event_attr,};static struct class kobject_event_class = { .name = "kobject_event", .owner = THIS_MODULE,};static int __init kobject_uevent_init(void){ int ret = 0; ret = class_register(&kobject_event_class); if (ret < 0) { printk(KERN_ERR "song_event: class_register fail\n"); return ret; } dev = device_create(&kobject_event_class, NULL, MKDEV(0, 0), NULL, "kobject_event"); if (dev) { ret = sysfs_create_group(&dev->kobj, &kobject_event_attr_group); if(ret < 0) { printk(KERN_ERR "kobject_event:sysfs_create_group fail\r\n"); return ret; } } else { printk(KERN_ERR "kobject_event:device_create fail\r\n"); ret = -1; return ret; } return 0;}static __exit void kobject_uevent_exit(void){ device_destroy(&kobject_event_class, MKDEV(0,0)); class_destroy(&kobject_event_class); sysfs_remove_group(&dev->kobj, &kobject_event_attr_group); printk(KERN_WARNING "kobject_uevent_exit!\n");}module_init(kobject_uevent_init);module_exit(kobject_uevent_exit); MODULE_LICENSE("GPL");MODULE_AUTHOR("haiyuexichen");
2、user端c文件user_kobject_uevent_env.c
#include #include #include #define UEVENT_MSG_LEN 4096int device_fd = -1;struct listener_gliethttp { const char *action; const char *path; const char *subsystem; const char *firmware; int major; int minor;};static int init_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);// uevent_fd_.Set(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 listener_gliethttp *listener_gliethttp){ listener_gliethttp->action = ""; listener_gliethttp->path = ""; listener_gliethttp->subsystem = ""; listener_gliethttp->firmware = ""; listener_gliethttp->major = -1; listener_gliethttp->minor = -1; printf("========================================================\n"); while (*msg) { printf("%s\n", msg); if (!strncmp(msg, "ACTION=", 7)) { msg += 7; listener_gliethttp->action = msg; } else if (!strncmp(msg, "DEVPATH=", 8)) { msg += 8; listener_gliethttp->path = msg; } else if (!strncmp(msg, "SUBSYSTEM=", 10)) { msg += 10; listener_gliethttp->subsystem = msg; } else if (!strncmp(msg, "FIRMWARE=", 9)) { msg += 9; listener_gliethttp->firmware = msg; } else if (!strncmp(msg, "MAJOR=", 6)) { msg += 6; listener_gliethttp->minor = atoi(msg); } else if (!strncmp(msg, "PANEL_ALIVE=", 12)) { printf("PANEL_ALIVE==%d\n",atoi(msg)); } while(*msg++) ; } printf("event { '%s', '%s', '%s', '%s', %d, %d }\n", listener_gliethttp->action, listener_gliethttp->path, listener_gliethttp->subsystem, listener_gliethttp->firmware, listener_gliethttp->major, listener_gliethttp->minor);}void UEventHandler() { char buffer[1024]; int ret; while (1) {printf("*******************************************************************\n");printf("waiting data sent for kernel!\n"); ret = read(device_fd, &buffer, sizeof(buffer)); if (ret == 0) { return; } else if (ret < 0) { printf("Got error reading uevent %d", ret); return; }printf("recevied message:\r\n"); for (int i = 0; i < ret;) { char *event = buffer + i; if (strcmp(event, "DEVTYPE=drm_minor")) ; else if (strcmp(event, "HOTPLUG=1")) { printf("hwc_uevent detect hotplug"); } printf("*********%s \r\n",event); i += strlen(event) + 1; } }}int main(){ char msg[UEVENT_MSG_LEN+2]; int n; device_fd = init_socket();if(device_fd<0){printf("fail to init socket!\r\n");return 0;}else{printf("success to init socket!\r\n");}UEventHandler(); while(1){ while((n = recv(device_fd, msg, UEVENT_MSG_LEN, 0)) > 0){ struct listener_gliethttp listener_gliethttp; if(n == UEVENT_MSG_LEN) continue; msg[n] = '\0'; msg[n+1] = '\0'; printf("----------- msg=%s\n",msg); parse_event(msg, &listener_gliethttp); printf("----------- msg=%s\n",msg); } }}
3、在android下真机执行效果
更多相关文章
- 在android中举例说明用Environment、StatFs以及DecimalFormat来
- Android之View基础总结(View的事件体系一)
- android startActivityForResult的用法
- 第3.1.4节 理解任务与返回堆栈
- android自定义menu,PopUpWindow弹出菜单
- Android项目开发中如何处理Home键
- Android(安卓)7.0新特性总结
- android:layout_weight越大所占比例越大和越大所占比例越小的两
- Android(安卓)调用网易微博开放API