1、mdev简介
linux驱动初学者往往有这样的体会,每次都需要手动创建设备节点,比较繁琐,使用设备管理文件系统则方便很多。在2.6的内核以前一直使用的是devfs,但是它存在许多缺陷,比如它创建了大量的设备文件,其实这些设备更本不存在。而且设备与设备文件的映射具有不确定性,比如U盘即可能对应sda,又可能对应sdb。没有足够的主/辅设备号。2.6之后的内核引入了sysfs文件系统,它挂载在/sys上,配合udev使用,可以很好的完成devfs的功能,并弥补了那些缺点。
mdev是busybox自带的一个简化版的udev,适合于嵌入式的应用埸合。其具有使用简单的特点。它的作用,就是在系统启动和热插拔或动态加载驱动程序时,自动产生驱动程序所需的节点文件。在以busybox为基础构建嵌入式linux的根文件系统时,使用它是最优的选择。
2、mdev使用方法
mdev的使用在busybox中的mdev.txt文档已经将得很详细了,下面以我的具体实现来进行讲解,我使用的busybox版本是1.13.3。
首先,需要在busybox的编译选项上添加对mdev的支持:
- Linux System Utilities --->
-
[*] mdev
-
[*] Support /etc/mdev.conf
-
[*] Support subdirs/symlinks
-
[*] Support regular expressions substitutions when renaming device
-
[*] Support command execution at device addition/removal
其次,需要在启动脚本里根据mdev.txt的要求做如下设置:
- Here's a typical code snippet from the init script:
-
[0] mount -t proc proc /proc
-
[1] mount -t sysfs sysfs /sys
-
[2] echo /sbin/mdev > /proc/sys/kernel/hotplug
-
[3] mdev -s
-
-
Alternatively, without procfs the above becomes:
-
[1] mount -t sysfs sysfs /sys
-
[2] sysctl -w kernel.hotplug=/bin/mdev
-
[3] mdev -s
-
-
-
Of course, a more "full" setup would entail executing this before the previous
-
code snippet:
-
[4] mount -t tmpfs -o size=64k,mode=0755 tmpfs /dev
-
[5] mkdir /dev/pts
-
[6] mount -t devpts devpts /dev/pts
注意:是/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug,并非/bin/echo /bin/mdev
> /proc/sys/kernel/hotplug。busybox的文档有错。
再次,需要在你的驱动中加上对类设备接口的支持,涉及到的接口函数及其原型如下:
class_create函数原型:
- /* This is a #define to keep the compiler from merging different
-
* instances of the __key variable */
-
#define class_create(owner, name) \
-
({ \
-
static struct lock_class_key __key; \
-
__class_create(owner, name, &__key); \
-
})
class_destroy函数原型:
- extern void class_destroy(struct class *cls);
device_create函数原型:
- extern struct device *device_create(struct class *cls, struct device *parent,
-
dev_t devt, void *drvdata,
-
const char *fmt, ...)
device_destroy函数原型:
- extern void device_destroy(struct class *cls, dev_t devt);
在驱动程序的初始化函数中,使用下述的类似语句,就能在类设备目录下添加包含设备号的名为“dev”的属性文件。并通过mdev在/dev目录下产生gpio_dev0的设备节点文件。
- gpio_class = class_create(THIS_MODULE, "gpio_class"); //mdev相关,用于自动创建设备节点
-
if(IS_ERR(gpio_class))
-
{
-
printk("Err: failed in creating class./n");
-
return -1;
-
}
-
/* register your own device in sysfs, and this will cause mdev to create corresponding device node */
-
device_create(gpio_class,NULL,dev_nr, NULL, "gpio_dev%d" ,0);
在驱动程序的清除程序段,加入以下语句,以完成清除工作。- device_destroy(gpio_class,dev_nr);
-
class_destroy(gpio_class);
需要的头文件是linux/device.h,因此程序的开始应加入下句 - #include <linux/device.h>
另外,my_class是class类型的结构体指针,要在程序开始时声明成全局变量。 上述程序中的gpio_major_number是设备的主节点号。可以换成需要的节点号。gpio_dev是最终生成的设备节点文件的名子。%d是用于以相同设备自动编号的。gpio_class是建立的class的名称,当驱动程序加载后,可以在/sys/class的目录下看到它,在本例中运行结果如下:
上述语句也不一定要在初始化和清除阶段使用,可以根据需要在其它地方使用。
至于/etc/mdev.conf文件,可有可无,不影响使用,只是添加了些功能。
现在简单说一下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 下创建设备节点文件。
最后,为了对上述内容进行说明,请各位同仁参考本博客驱动案例中的相关驱动程序加以理解。
enjoy!
阅读(2401) | 评论(0) | 转发(1) |