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下真机执行效果

更多相关文章

  1. 在android中举例说明用Environment、StatFs以及DecimalFormat来
  2. Android之View基础总结(View的事件体系一)
  3. android startActivityForResult的用法
  4. 第3.1.4节 理解任务与返回堆栈
  5. android自定义menu,PopUpWindow弹出菜单
  6. Android项目开发中如何处理Home键
  7. Android(安卓)7.0新特性总结
  8. android:layout_weight越大所占比例越大和越大所占比例越小的两
  9. Android(安卓)调用网易微博开放API

随机推荐

  1. Android(安卓)TabLayout 结合ViewPager实
  2. Android(安卓)PackageInstaller 安装和卸
  3. CardView卡片效果
  4. Android(安卓)自定义可编辑可任意全屏拖
  5. LayoutParams基本使用
  6. [Android]aapt命令小结
  7. 已解决:Error: Static interface methods
  8. Android(安卓)Sqlite数据库详解
  9. android-搭建本地maven仓库
  10. android 6.0 healthd vold接收uevent