Chinaunix首页 | 论坛 | 博客
  • 博客访问: 34097
  • 博文数量: 13
  • 博客积分: 92
  • 博客等级: 民兵
  • 技术积分: 95
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-18 16:04
个人简介

飞飞有话说

文章分类
文章存档

2011年(13)

分类:

2011-12-14 20:35:30

一.>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文件系统:http://blog.chinaunix.net/u1/55599/showart_1089096.html
   上篇文章简单介绍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/目录树,他和文件系统分开。知道如何改变缺省配置能让你如何定制自己的系统,比如创建设备字符连接,改变设备文件属组,权限等。

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