Chinaunix首页 | 论坛 | 博客
  • 博客访问: 263882
  • 博文数量: 84
  • 博客积分: 3742
  • 博客等级: 中校
  • 技术积分: 870
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-20 19:38
文章分类

全部博文(84)

文章存档

2012年(6)

2011年(21)

2010年(54)

2009年(3)

分类: LINUX

2010-08-16 09:49:08

一.>devfs设备文件简略介绍(2.6版本以后内核都采用udev设备文件系统)
    devfs(设备文件系统)是由2.4内核引入的,具有如下优点:
    1.可以通过程序在设备初始化时在/dev目录下创建设备文件,卸载时将它删除。
    2.设备驱动程序可以指定设备号,所有者,和权限位,用户空间可以修改所有者和权限位。
    3.不再需要为设备驱动程序分配主设备号以及处理的次设备号,在程序可以直接
      给register_chrdev()传递0主设备号以动态获得可用的主设备号,并在devfs_register()
      中指定次设备号。
    在2.6内核以前一直使用的是 devfs,devfs挂载于/dev目录下,提供了一种类似于文件的方法来管理位于/dev目录下的所有设备,我们知道
    /dev目   录下的每一个文件都对应的是一个设备,至于当前该设备存在与否先且不论,而且这些特殊文件是位于根文件系统上的,在制作文件系统
    的时候我们就已经建立了这些设备文件,因此通过操作这些特殊文件,可以实现与内核进行交互。但是devfs文件系统有一些缺点,例如:不确定的
    设备映射,有时一个设备映射的设备文件可能不同,例如我的U盘可能对应sda有可能对应sdb;没有足够的主/辅设备号,当设备过多的时候,
    显然这会成为一个问题;/dev目录下文件太多而且不能表示当前系统上的实际设备;命名不够灵活,不能任意指定等等。
二.>udev设备文件详细介绍
   devfs 存在的主要的问题是它处理设备检测、创建和命名的方式,其中设备节点的命名可能是最严重的问题。一般可接受的方式是,如果设备名
   是可配置的,那么设备命名策略应该由系统管理员决定,而不是由某些开发者强制规定。devfs 文件系统还存在竞争条件(race conditions)
   的问题,这是它天生的设计缺陷,不对内核做彻底的修改就无法修正这个问题。
   上篇文章简单介绍sysfs文件系统,您可能想知道 sysfs 是怎么认出系统中存在的设备以及应该使用什么设备号。对于已经编入内核的驱动程序,
   当被内核检测到的时候,会直接在 sysfs 中注册其对象;对于编译成模块的驱动程序,当模块载入的时候才会这样做。一旦挂载了 sysfs 文
   件系统(挂载到 /sys),内建的驱动程序在 sysfs 注册的数据就可以被用户空间的进程使用,并提供给 udev 以创建设备节点。
   udev 初始化脚本负责在 Linux 启动的时候创建设备节点,该脚本首先将 /sbin/udevsend 注册为热插拔事件处理程序。热插拔事
   件(随后将讨论)本不应该在这个阶段发生,注册 udev 只是为了以防万一。然后 udevstart 遍历 /sys 文件系统,并在 /dev 目录下创建符
   合描述的设备。例如,/sys/class/tty/vcs/dev 里含有"7:0"字符串,udevstart 就根据这个字符串创建主设备号为 7 、次设备号为 0
   的 /dev/vcs 设备。udevstart 创建的每个设备的名字和权限由 /etc/udev/rules.d/ 目录下的文件指定的规则来设置。如果 udev 找不
   到所创建设备的权限文件,就将其权限设置为缺省的 660 ,所有者为 root:root 。
   上面的步骤完成后,那些已经存在并且已经内建驱动的设备就可以使用了,那么以模块驱动的设备呢?
   前面我们提到了"热插拔事件处理程序"的概念,当内核检测到一个新设备连接时,内核会产生一个热插拔事件,
   并在 /proc/sys/kernel/hotplug 文件里查找处理设备连接的用户空间程序。udev 初始化脚本将 udevsend 注册为该处理程序。
   当产生热插拔事件的时候,内核让 udev 在 /sys 文件系统里检测与新设备的有关信息,并为新设备在 /dev 里创建项目。
   大多数 Linux 发行版通过 /etc/modules.conf 配置文件来处理模块加载,对某个设备节点的访问导致相应的内核模块被加载。对 udev 这
   个方法就行不通了,因为在模块加载前,设备节点根本不存在。为了解决这个问题,在 LFS-Bootscripts 软件包里加入了 modules 启动脚
   本,以及 /etc/sysconfig/modules 文件。通过在 modules 文件里添加模块名,就可以在系统启动的时候加载这些模块,这样 udev 就
   可以检测到设备,并创建相应的设备节点了。如果插入的设备有一个驱动程序模块但是尚未加载,Hotplug 软件包就有用了,它就会响应
   上述的内核总线驱动热插拔事件并加载相应的模块,为其创建设备节点,这样设备就可以使用了。
   udev是一种工具,它能够根据系统中的硬件设备的状况动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下,
   使用udev 后,在/dev下面只包含系统中真实存在的设备。它于硬件平台无关的,位于用户空间,需要内核sysfs和tmpfs的支持,sysfs为
   udev提供设备入口和uevent通道,tmpfs为udev设备文件提供存放空间。

   显而易见udev设备文件的优点:
   1.udev完全在用户态工作,利用设备加入或移除时内核所发送的热插拔事件。在热插拔时,设备的详细信息会由内核输出到位于/sys的sysfs
   文件系统。udev的设备命名策略权限控制都在用户态完成的,它利用sysfs信息来进行创建设备文件节点。
   2.udev根据系统中的硬件设备的状态动态更新设备文件,进行设备文件的创建和删除等。
   注:使用udev,/dev目录下就会只包含系统中真正存在的设备。
   
   注:所有在 sysfs 中显示的设备都可以由 udev 来创建节点。如果内核中增加了其它设备的支持,
   udev 也就自动地可以为它们工作了。在init初始化之前,udev 可以被放入 initramfs 之中,并在每个设备被发现的时候运行。
   也可以让udev 工作在一个真的根分区被加载之后根据 /sys 的内容创建的初始 /dev 目录之中
   
三.>udev和devfs设备文件的对比
1.udev能够实现所有devfs实现的功能。但udev运行在用户模式中,而devfs运行在内核中。
2.当一个并不存在的 /dev 节点被打开的时候, devfs一样自动加载驱动程序而udev确不能。
  udev设计时,是在设备被发现的时候加载模块,而不是当它被访问的时候。
  devfs这个功能对于一个配置正确的计算机是多余的。系统中所有的设备都应该产生
  hotplug 事件、加载恰当的驱动,而 udev 将会注意到这点并且为它创建对应的
  设备节点。如果你不想让所有的设备驱动停留在内存之中,应该使用其它东西来
  管理你的模块 (如脚本, modules.conf, 等等) 。
  其中devfs 用的方法导致了大量无用的 modprobe 尝试,以此程序探测设备是否存在。
  每个试探性探测都新建一个运行 modprobe 的进程,而几乎所有这些都是无用的。
  
3.udev是通过对内核产生的设备名增加别名的方式来达到上述目的的。前面说过,udev是用户模式程序,不会更改内核的行为。
因此,内核依然会我行我素地产生设备名如sda,sdb等。但是,udev可以根据设备的其他信息如总线(bus),生产商(vendor)等
不同来区分不同的设备,并产生设备文件。udev只要为这个设备文件取一个固定的文件名就可以解决这个问题。在后续对设备的操作中,
只要引用新的设备名就可以了。但为了保证最大限度的兼容,一般来说,
新设备名总是作为一个对内核自动产生的设备名的符号链接(link)来使用的。
    例如:内核产生了sda设备名,而根据信息,这个设备对应于是我的内置硬盘,那我就可以制定udev规则,让udev除了产生/dev/sda设备文件 外,另外创建一个符号链接叫/dev/internalHD。这样,我在fstab文件中,就可以用/dev/internalHD来代替原来的 /dev/sda了。下次,由于某些原因,这个硬盘在内核中变成了sdb设备名了,那也不用着急,udev还会自动产生/dev/internalHD这 个链接,并指向正确的/dev/sdb设备。所有其他的文件像fstab等都不用修改。
     而在在2.6内核以前一直使用的是 devfs,devfs挂载于/dev目录下,提供了一种类似于文件的方法来管理位于/dev目录下的所有设备,但是devfs文件系统有一些缺点,例 如:不确定的设备映射,有时一个设备映射的设备文件可能不同,例如我的U盘可能对应sda有可能对应sdb 。
注:可以用命令查看其中的信息,    udevinfo -a -p /sys/block/sda
在此之前的设备文件管理方法(静态文件和devfs)有几个缺点:
* 不确定的设备映射。特别是那些动态设备,比如USB设备,设备文件到实际设备的映射并不可靠和确定。举一个例子:如果你有两个USB打印机。一个可能称为 /dev/usb/lp0,另外一个便是/dev/usb/lp1。但是到底哪个是哪个并不清楚,lp0,lp1和实际的设备没有一一对应的关系,因为他 可能因为发现设备的顺序,打印机本身关闭等原因而导致这种映射并不确定。理想的方式应该是:两个打印机应该采用基于他们的序列号或者其他标识信息的唯一设 备文件来映射。但是静态文件和devfs都无法做到这点。
*没有足够的主/辅设备号。我们知道,每一个设备文件是有两个8位的数字:一个是主设备号 ,另外一个是辅设备号来分配的。这两个8位的数字加上设备类型(块设备或者字符设备)来唯一标识一个设备。不幸的是,关联这些身边的的数字并不足够。
*/dev目录下文件太多。一个系统采用静态设备文件关联的方式,那么这个目录下的文件必然是足够多。而同时你又不知道在你的系统上到底有那些设备文件是激活的。
*命名不够灵活。尽管devfs解决了以前的一些问题,但是它自身又带来了一些问题。其中一个就是命名不够灵活;你别想非常简单的就能修改设备文件的名字。缺省的devfs命令机制本身也很奇怪,他需要修改大量的配置文件和程序。;
*内核内存使用,devfs特有的另外一个问题是,作为内核驱动模块,devfs需要消耗大量的内存,特别当系统上有大量的设备时(比如上面我们提到的系统一个上有好几千磁盘时)
udev的目标是想解决上面提到的这些问题,他通采用用户空间(user-space)工具来管理/dev/目录树,他和文件系统分开。知道如何改变缺省配置能让你如何定制自己的系统,比如创建设备字符连接,改变设备文件属组,权限等。

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/55599/showart_1089378.html
阅读(804) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~