hotplug_uevent机制学习笔记

来源:互联网 发布:mac skype 下载 编辑:程序博客网 时间:2024/05/01 18:03

1、为什么有hotplug_uevent机制

(1)查看驱动程序,以前是构造file_operation结构体。


(2)在入口函数来注册它。


(3)为什么还要创建类,为什么还要在类下创建设备,这样做是为了让mdev根据这些信息来创建设备节点

(4)分析为什么class_device_create这个函数能让mdev创建设备节点

class_device_create
    class_device_register
         class_device_add
            kobject_uevent(&class_dev->kobj, KOBJ_ADD);
            kobject_uevent_env(kobj, action, NULL);
             / / action_string = "add";
             action_string = action_to_string(action);


              /* 分配保存环境变量的内存 */
              /* environment values */
           buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);

           /* 设置环境变量 */
          envp [i++] = scratch;
          scratch += sprintf(scratch, "ACTION=%s", action_string) + 1;
          envp [i++] = scratch;
          scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
          envp [i++] = scratch;
          scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;

          /* 调用应用程序: 比如mdev */
         /* 启动脚本 echo /sbin/mdev > /proc/sys/kernel/hotplug 
         * 设置了uevent_helper为“/sbin/mdev“
          */


          argv [0] = uevent_helper;  // 假设argv [0] = "/sbin/mdev"
          argv [1] = (char *)subsystem;
          argv [2] = NULL;
          call_usermodehelper (argv[0], argv, envp, 0);//创建一个进程argv[0](调用应用             程序),应用程序根据环境变envp量来创建设备节点

(4)打印应用程序的名字argv[0]和环境变量envp

这里在循环打印环境变量中,其环境变量的循环次数界限值用envp[i],主要是想数组元素不存在时退出。


应用程序根据环境变量来创建设备节点。

2、实验

(1)修改内核程序



(2)编译内核make uImage并把编译好的内核拷贝到网络文件系统那里去


(3)reboot命令重启开发板用新内核启动


(4)启动内核


(5)把编译好的驱动模块拷贝到网络文件系统


(6)装载模块

可以看出uevent_helper函数是/sbin/mdev,打印出来的环境变量存在问题

3、环境变量打印存在问题,缺少一个变量


(1)重新执行之前操作出现各种环境变量 


(3)装载驱动

驱动程序里面会调用class_device_create函数,最终调用call_usermodehelper (argv[0], argv, envp, 0);//创建一个进程argv[0](调用应用程序/sbin/mdev),应用程序根据环境变envp量来创建设备节点


4、应用程序根据环境变envp量来创建设备节点分析

(1)分析busybox的mdev.c里面的main 函数



如果不是mdev -s,是指一开始启动的时候


(2)在etc/init.d/rcS中有mdev -s



(3)看mdev的意思

带-s参数是在系统启动时扫描/sys and populate这个目录,根据里面的信息创建各种设备节点,产生/dev目录


(4)mdev_main函数分析


上面打印环境变量时已经知道action等于add,也就是执行make_device(temp, 0)函数。

  • make_device(temp, 0)函数中//创建设备节点
如果有mdev.conf配置文件,会根据这个配置文件创建设备节点的名称(这个暂时不用)

  • 因为temp = /sys/class/sixth_drv/buttons,因为temp等于envpath,而envpath等于DEVPATH,查看打印出来的环境变量可知DEVPATH=/class/sixth_drv/buttons


  • bb_basename(path)这里的path和上面的temp等价

下面分析bb_basename()函数,strrchr函数是找到name里面倒数第一个反斜杠,返回这个斜杠后面的字符串,也就是找到buttons,设备节点的名字就定下来了啦


类型根据path数组的第5个元素是否为'c'来判断,'c' == > 字符设备节点。根据上面分析path等于temp ,看temp = /sys/class/sixth_drv/buttons中第5个值,应该是c,应该是字符设备,也就是class目录下都是字符设备


  • 看make_device函数
看里面的strcat函数

extern char *strcat(char *dest, const char *src);

把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')。
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
返回指向dest的指针。


  • 看主次设备号
也就是扫描temp指定的目录,把里面的dev文件读取出来,确定主设备号和次设备号


创建设备节点,这里的设备文件名device_name = bb_basename(path);  = "buttons"。




5、知识点回顾

(1)mdev_main函数根据传进来的环境变量,根据action是add就创建设备节点。根据devpath这个参数在前面加一个/sys创建设备节点


(2)创建设备节点(知道设备名字,设备类型(字符设备,块设备,网络设备),主次设备号)


(3)根据/sys/class/sixth_drv/buttons目录下的dev下的内容确定主次设备号

         根据/sys/class/sixth_drv/buttons目录中第5个字符是否为C来判断是否为字符类型的设备

(4)我们的驱动程序在类下面创建设备节点(通过class_device_create这个函数),最终会导致调用call_usermodehelper这个函数会调用应用程序(一般设置为/sbin/mdev),这个应用程序会根据环境变量来创建设备节点。

(5)uevent_helper为什么是“/sbin/mdev“,在启动脚本里/etc/init.d/rcS里有

echo /sbin/mdev >/proc/sys/kernel/hotplug

因而设置字符串uevent_helper为“/sbin/mdev“

(6)在出口函数里面有class_device_unregister函数

这个函数类似于class_device_create这个函数


卸载驱动,可以看到action等于remove


0 0