Chinaunix首页 | 论坛 | 博客
  • 博客访问: 94482
  • 博文数量: 17
  • 博客积分: 691
  • 博客等级: 上士
  • 技术积分: 220
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-27 08:50
文章分类
文章存档

2012年(1)

2011年(16)

分类: 嵌入式

2011-08-02 10:19:26

    1、mdev简介
    
    linux驱动初学者往往有这样的体会,每次都需要手动创建设备节点,比较繁琐,使用设备管理文件系统则方便很多。在2.6的内核以前一直使用的是devfs,但是它存在许多缺陷,比如它创建了大量的设备文件,其实这些设备更本不存在。而且设备与设备文件的映射具有不确定性,比如U盘即可能对应sda,又可能对应sdb。没有足够的主/辅设备号。2.6之后的内核引入了sysfs文件系统,它挂载在/sys上,配合udev使用,可以很好的完成devfs的功能,并弥补了那些缺点。
    mdevbusybox自带的一个简化版的udev,适合于嵌入式的应用埸合。其具有使用简单的特点。它的作用,就是在系统启动和热插拔或动态加载驱动程序时,自动产生驱动程序所需的节点文件。在以busybox为基础构建嵌入式linux的根文件系统时,使用它是最优的选择。
    
    2、mdev使用方法
    
   mdev的使用在busybox中的mdev.txt文档已经将得很详细了,下面以我的具体实现来进行讲解,我使用的busybox版本是1.13.3。
   首先,需要在busybox的编译选项上添加对mdev的支持:  
  1. Linux System Utilities --->
  2.     [*] mdev
  3.     [*] Support /etc/mdev.conf
  4.     [*] Support subdirs/symlinks
  5.     [*] Support regular expressions substitutions when renaming device
  6.     [*] Support command execution at device addition/removal
   其次,需要在启动脚本里根据mdev.txt的要求做如下设置:
  1. Here's a typical code snippet from the init script:
  2. [0] mount -t proc proc /proc
  3. [1] mount -t sysfs sysfs /sys
  4. [2] echo /sbin/mdev > /proc/sys/kernel/hotplug
  5. [3] mdev -s

  6. Alternatively, without procfs the above becomes:
  7. [1] mount -t sysfs sysfs /sys
  8. [2] sysctl -w kernel.hotplug=/bin/mdev
  9. [3] mdev -s


  10. Of course, a more "full" setup would entail executing this before the previous
  11. code snippet:
  12. [4] mount -t tmpfs -o size=64k,mode=0755 tmpfs /dev
  13. [5] mkdir /dev/pts
  14. [6] mount -t devpts devpts /dev/pts

    注意:是/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug,并非/bin/echo /bin/mdev > /proc/sys/kernel/hotplugbusybox的文档有错。

    再次,需要在你的驱动中加上对类设备接口的支持,涉及到的接口函数及其原型如下:

    class_create函数原型:

  1. /* This is a #define to keep the compiler from merging different
  2.  * instances of the __key variable */
  3. #define class_create(owner, name)        \
  4. ({                        \
  5.     static struct lock_class_key __key;    \
  6.     __class_create(owner, name, &__key);    \
  7. })

     class_destroy函数原型:   

  1. extern void class_destroy(struct class *cls);

device_create函数原型:

  1. extern struct device *device_create(struct class *cls, struct device *parent,
  2.                  dev_t devt, void *drvdata,
  3.                  const char *fmt, ...)

device_destroy函数原型:

  1. extern void device_destroy(struct class *cls, dev_t devt);

在驱动程序的初始化函数中,使用下述的类似语句,就能在类设备目录下添加包含设备号的名为“dev”的属性文件。并通过mdev/dev目录下产生gpio_dev0的设备节点文件。

  1. gpio_class = class_create(THIS_MODULE, "gpio_class");    //mdev相关,用于自动创建设备节点
  2. if(IS_ERR(gpio_class))
  3. {
  4.     printk("Err: failed in creating class./n");
  5.     return -1;
  6. }
  7. /* register your own device in sysfs, and this will cause mdev to create corresponding device node */
  8. device_create(gpio_class,NULL,dev_nr, NULL, "gpio_dev%d" ,0);

    在驱动程序的清除程序段,加入以下语句,以完成清除工作。
  1. device_destroy(gpio_class,dev_nr);
  2. class_destroy(gpio_class);
    需要的头文件是linux/device.h,因此程序的开始应加入下句   
  1. #include <linux/device.h>
    
另外,my_classclass类型的结构体指针,要在程序开始时声明成全局变量。   
  1. struct class *my_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!

阅读(2393) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~