Linux设备模型 热插拔、mdev 与 firmware
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux设备驱动程序学习(15)
-Linux设备模型(热插拔、mdev 与firmware)
热插拔
有2 个不同角度来看待热插拔:
从内核角度看,热插拔是在硬件、内核和内核驱动之间的交互。
从用户角度看,热插拔是内核和用户空间之间,通过调用用户空间程序(如hotplug、udev 和mdev)的交互。
当需要通知用户内核发生了某种热插拔事件时,内核才调用这个用户空间程序。
现在的计算机系统,要求Linux 内核能够在硬件从系统中增删时,可靠稳定地运行。
这就对设备驱动作
者增加了压力,因为在他们必须处理一个毫无征兆地突然出现或消失的设备。
热插拔工具
当用户向系统添加或删除设备时,内核会产生一个热插拔事件,并在/proc/sys/kernel/hotplug文件里查找处理设备连接的用户空间程序。
这个用户空间程序主要有
hotplug:这个程序是一个典型的bash 脚本,只传递执行权给一系列位于/etc/hot-plug.d/ 目录树的程序。
hotplug 脚本搜索所有的有 .hotplug 后缀的可能对这个事件进行处理的程序并调用它们, 并传递给它们许多不同的已经被内核设置的环境变量。
(基本已被淘汰,具体内容请参阅《LDD3》)
udev :用于linux2.6.13或更高版本的内核上,为用户空间提供使用固定设备名的动态/dev目录的解
决方案。
它通过在sysfs 的/class/ 和/block/ 目录树中查找一个称为dev 的文件,以确定所创建的
设备节点文件的主次设备号。
所以要使用udev,驱动必须为设备在sysfs中创建类接口及其dev属性文件,方法和sculld模块中创建dev属性相同。
udev的资料网上十分丰富,我就不在这废话了,给出以
下链接有兴趣的自己研究:
mdev:一个简化版的udev,是busybox所带的程序,十分适合嵌入式系统。
因为hotplug现在也在被慢慢地淘汰,udev不再依赖hotplug了,所以这里不再介绍;
udev较mdev复杂,不太适合嵌入式使用。
(本人也有做udev的实验,交叉编译是通过了,但是使用上有问题,没有实现其功能。
也许是我的文件系统没做好,以后有时间再研究和写记录。
有成功高人的通知一声,交流一下经验。
^_^谢谢!);
mdev简单易用,比较适合嵌入式系统,实验成功。
以下详细介绍mdev的使用。
mdev
在一开始建立根文件系统时,我根据WeiBing 的博客上《UDEV on embeded Linux-2.6.19.2》(地址:/logs/4485453.html)这篇文章的提示,开始使用mdev,但是当时只是启动时mdev -s 一下,并没有深究。
现在在学习了Linux设备模型之后,对于Linux中/dev目录的动态管理有了更深的认识,并认真的看了一下busybox中的mdev.txt文档并翻译了一下,做成了PDF(下载地址:/blog/upfile2/080111091002.pdf),在看下面的内容时请先看看这篇文档。
先声明一个要点:要实现设备节点文件的自动、动态的增删,必须在你自己的驱动源码中实现类接口,并在类设备的目录中添加包含设备号的名为“dev”的属性文件。
mdev原理及bug
要使用mdev,适当知道一下原理是必不可少的(能完整地研究mdev源码是最好的)。
说实话起初我并没有想看mdev的源码,是在使用时发现了问题后才去研究了一下mdev的源码。
现在简单介绍一下mdev 的原理:
执行mdev -s:以…-s‟为参数调用位于/sbin目录写的mdev(其实是个链接,作用是传递参数给/bin
目录下的busybox程序并调用它),mdev扫描/sys/class 和/sys/block 中所有的类设备目录,如果在目录中含有名为“dev”的文件,且文件中包含的是设备号,则mdev就利用这些信息为这个设备在/dev 下创建设备节点文件。
一般只在启动时才执行一次“mdev -s”。
热插拔事件:由于启动时运行了命令:echo /sbin/mdev > /proc/sys/kernel/hotplug ,那么当有热插拔事件产生时,内核就会调用位于/sbin目录的mdev。
这时mdev通过环境变量中的 ACTION 和DEVPATH,来确定此次热插拔事件的动作以及影响了/sys中的那个目录。
接着会看看这个目录中是否有“dev”的属性文件,如果有就利用这些信息为这个设备在/dev 下创建设备节点文件。
mdev使用
mdev的使用在busybox中的mdev.txt文档已经将得很详细了。
但作为例子,我简单讲讲我的使用过程:
(1)在编译时加上对mdev的支持(我是使用的是busybox1.9.0):
Linux System Utilities --->
[*] mdev
[*] Support /etc/mdev.conf
[*] Support command execution at device addition/removal
(2)在启动时加上使用mdev的命令:
我在自己创建的根文件系统(nfs)中的/linuxrc文件中添加了如下指令:
注意:是
/bin/mdev >/proc/sys/kernel/hotplug。
busybox的文档有错!!
(3)在你的驱动中加上对类设备接口的支持,并在类设备目录下添加包含设备号的名为“dev”的属性文件。
(4)至于/etc/mdev.conf文件,可有可无,不影响使用,只是添加了些功能。
为了实验我在/etc创建了mdev.conf文件并输入了:
具体的实验源码和现象在文章后面有。
firmware
硬件市场的激烈竞争, 使得制造商连一点用于设备控制固件的EEPROM 的成本都不愿意花费。
因此固件一般发布在和硬件配套的驱动包中,由操作系统(其实是驱动程序)负责传送固件到设备。
内核固件接口
获取固件的正确方法是当需要时从用户空间获取它。
一定不要试图从内核空间直接打开包含固件的文件,那是一个易出错的操作, 因为它把策略(以文件名的形式)包含进了内核。
正确的方法是使用固件接口:
注意:要使用firmware,必须要在配置内核时选上:
Device Drivers --->
Generic Driver Options --->
<*> Userspace firmware loading support
否则会出现: Unknown symbol release_firmware 和: Unknown symbol request_firmware 的错误。
固件接口工作原理
固件子系统使用sysfs 和热插拔机制工作。
当调用request_firmware时, 函数将在
/sys/class/firmware 下创建一个以设备名为目录名的新目录,其中包含3 个属性:
loading:这个属性应当被加载固件的用户空间进程设置为1。
当加载完毕, 它将被设为0。
被设为-1 时,将中止固件加载。
data:一个用来接收固件数据的二进制属性。
在设置loading 为1后, 用户空间进程将固件写入这个属
性。
device:一个链接到/sys/devices 下相关入口项的符号链接。
一旦创建了sysfs 入口项, 内核将为设备产生一个热插拔事件,并传递包括变量FIRMWARE 的环境变量给处理热插拔的用户空间程序。
FIRMWARE 被设置为提供给request_firmware 的固件文件名。
用户空间程序定位固件文件, 并将其拷贝到内核提供的二进制属性;若无法定位文件, 用户空间程序设置loading 属性为-1。
若固件请求在10 秒内没有被服务, 内核就放弃并返回一个失败状态给驱动。
超时周期可通过sysfs 属性/sys/class/firmware/timeout 属性改变。
request_firmware 接口允许使用驱动发布设备固件。
当正确地集成进热插拔机制后, 固件加载子系统允许设备不受干扰地工作。
显然这是处理问题的最好方法,但固件受版权保护,小心违反版权法。
ARM9开发板实验
实验源码:
/blog/upfile2/080114113255. gz。