第28课 hotplug/uevent机制

第28课 hotplug/uevent机制

第一节 hotplug/uevent机制的介绍

热拔插设备

先来回顾之前的按键字符设备驱动程序:
首先创建一个file_operations结构体,
第28课 hotplug/uevent机制
之后在入口函数中注册该设备,然后再创建类,再在类下创建设备:
第28课 hotplug/uevent机制
这里有个问题:为什么要在注册了设备之后要创建类并在类下创建一个设备呢??
这么做的目的是为了让mdev根据这些信息来创建设备节点
mdev又是如何根据提供的信息来创建设备节点的呢?
分析class_device_create()函数:
第28课 hotplug/uevent机制

环境变量:环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。
环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。例如Windows和DOS操作系统中的path环境变量,当要求系统运行一个程序而没有告诉它程序所在的完整路径时,系统除了在当前目录下面寻找此程序外,还应到path中指定的路径去找。用户通过设置环境变量,来更好的运行进程。
shell环境依赖于多个文件的设置。当shell被调用时,它从两个初始文件读取命令。/etc/profile包含了系统变量,它由系统管理员维护,由系统管理员设置本地系统变量和特殊命令。普通用户的启动信息文件($HOME/.bash_project)由各用户自己维护,该文件可以被修改以实现任何特定的系统初始化。

在开发板的内核中执行env命令可以查看环境变量:
第28课 hotplug/uevent机制
这些环境变量就是系统在执行相应的应用程序时所要读取的重要参数,每一个应用程序都有环境变量。
第28课 hotplug/uevent机制
调用了应用程序后,应用程序(如mdev)就会根据之前设置好的环境变量来创建设备节点。(猜测)

现在来验证这里的uevent_helper是不是mdev应用程序,可以通过添加打印语句的方式来验证:
第28课 hotplug/uevent机制
将上述打印语句添加至开发板Linux内核中的相应文件中:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
之后重新编译内核:
第28课 hotplug/uevent机制
将新编译的内核映象拷贝至网络文件系统中:
第28课 hotplug/uevent机制
用新内核启动开发板并装载了之前的按键驱动程序后发现出现了很多打印语句:
第28课 hotplug/uevent机制
从这里能够看出这里的uevent_helper就是mdev应用程序。但是目前这里的打印的环境变量有点问题。
第28课 hotplug/uevent机制
修改后重新启动,发现在启动过程中打印出来各种环境变量:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
分析:装载驱动程序后,就会根据之前分析的,进入class_device_create()函数一路执行到call_usermodehelper(argv[0], argv, envp, 0)调用uevent_helper字符串所指向(设置)的应用程序:即/sbin/mdev。之后mdev应用程序就会根据设置的一系列环境变量来创建设备节点。(猜测)
第28课 hotplug/uevent机制
那到底是不是真如我们猜测的过程??
来分析busybox中mdev的源码:(以之前加载按键驱动程序为例)
第28课 hotplug/uevent机制
这里的“-s”参数代表的是当系统启动时扫描/sys目录并产生/dev目录并生成各种设备节点:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
注意:sprintf(temp, “/sys%s”, env_path);的意思是将/sys+env_path输出到 temp 所指向的字符串。

这里的意思是如果action环境变量是“add”,则创建设备节点make_device().
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
完整梳理:
驱动程序中在类下创建设备节点:class_device_create()—>call_usermodehelper(),这里的应用程序一般设置为/sbin/mdev,之后应用程序就会根据环境变量创建设备节点。

问题:call_usermodehelper()函数如何知道uevent_helper变量中传入的就是mdev应用程序呢??
第28课 hotplug/uevent机制
启动脚本中的“echo /sbin/mdev > /proc/sys/kernel/hotplug”语句设置了uevent_helper为“/sbin/mdev”。

在出口函数中卸载驱动的时候调用class_device_unregister()函数,其中同样最终会调用到call_usermodehelper()函数最终导致应用程序mdev被调用,只不过卸载时环境变量不同,之前是add,现在变为remove,最终删除设备节点。
第28课 hotplug/uevent机制

第二节 hotplug/uevent机制–修改mdev配置支持U盘自动挂载

问题:接上U盘想自动挂载怎么做??
第28课 hotplug/uevent机制
可以看到/dev/sda表示整个U盘,/dev/sda1表示这个U盘的第一个分区,现在需要手动挂载U盘分区:
第28课 hotplug/uevent机制
现在想达到的效果是自动挂载+自动卸载;----通过mdev工具来实现。
在busybox的mdev.c代码中可以看到,如果内核中使用了mdev配置文件mdev.conf,则在系统启动后会根据该配置文件的内容进行一些操作。
第28课 hotplug/uevent机制
相反,如果没有使用配置文件,则只创建设备节点:
第28课 hotplug/uevent机制
因此可以通过配置文件来达到我们想要自动挂载U盘的目的。
使用方法:在busybox工程中搜索mdev,找到一个mdev.txt文档:里面有配置文档的写法
第28课 hotplug/uevent机制
mdev.conf的格式:

<device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]

device regex:设备的正则表达式 ,表示哪一个设备
uid:用户
gid:组ID
octal permissions:八进制权限属性,可读可写等权限
The special characters have the meaning: 
	@ Run after creating the device. //创建设备节点后运行命令
	$ Run before removing the device. //删除设备节点之前执行命令
	* Run both after creating and before removing the device.//创建设备节点之后和删除设备节点之前都运行该命令

想要实现自动挂载,就可以通过在mdev.conf中写入一条这样的指令,mdev去读该配置文件,之后会以octal permissions权限创建device设备节点,并且会执行后面command命令

正则表达式: 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。
很可能你使用过Windows/Dos下用于文件查找的通配符(wildcard),也就是和?。如果你想查找某个目录下的所有的Word文档的话,你会搜索.doc。在这里,*会被解释成任意的字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求——当然,代价就是更复杂——比如你可以编写一个正则表达式,用来查找所有以0开头,后面跟着2-3个数字,然后是一个连字号“-”,最后是7或8位数字的字符串(像010-12345678或0376-7654321)。
正则表达式的一些常用规则:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
[xxxx] 表示这些字符里的某一个。如[abc]表示abc中的某一个字符,[1-9]表示1-9中的某一个数字。

现在来做一个例子: 加载之前的led驱动程序:
第28课 hotplug/uevent机制
可以看到所有的led设备权限都是可读可写可执行的,现在想要更改led设备的权限。
就要通过写配置文件的方式来完成:
1)首先写设备的正则表达式,用一个正则表达式来同时表示led1-3和leds。
①可以先不用正则表达式:在mdev.conf中直接罗列写出配置命令:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
这时候权限已经被改写了。

② 正则表达式:
第28课 hotplug/uevent机制
③ 再加入命令:装载驱动程序后执行打印命令:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
在命令中又加入一段脚本,表示根据环境变量来打印不同的提示语句。

④ 将命令写入一个脚本:add_remove_led.sh,然后把该脚本放入一个目录/bin 中:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
可以看到达到了同样的效果。

⑤ U盘自动加载:
第28课 hotplug/uevent机制
第28课 hotplug/uevent机制
这时候看到已经成功自动挂载了。拔掉U盘后可以看到已经没有挂载信息了:
第28课 hotplug/uevent机制
当然也可以把后面的命令写为sh脚本文件:
第28课 hotplug/uevent机制