现在的位置: 首页 > 综合 > 正文

linux udev设备管理

2013年10月12日 ⁄ 综合 ⁄ 共 8517字 ⁄ 字号 评论关闭

1.udev 配置文件介绍:

   主要的udev配置文件是/etc/udev/udev.conf;这个文件一般只有下面几行,#开头的为注释,其他为选项;

   udev_root="/dev/"

   udev_rules="/etc/udev/rules.d"

   udev_log="err"

   第一行表示,udev的根目录就是/dev;

   第二行表示,udev使用的规则在/etc/udev/rules.d目录下,该目录下可能有多个规则文件,通常是数字+字符串.rules;

数字表示应用该规则的顺序,每次udev都到该目录下寻找相应的匹配并按照设置选项进行操作;

   第三行表示,udev错误写入日志文件syslog里面;

2.udev配置项介绍

规则文件里的规则有一系列的键/值对组成,键/值对之间用逗 号(,)分割。每一个键或者是用户匹配键,或者是一个赋值键。匹配键确定规则是否被应用,而赋值键表示分配某值给该键。这些值将影响udev创建的设备文 件。赋值键可以处理一个多值列表。匹配键和赋值键操作符解释见下表:

                       udev 键/值对操作符
操作符     匹配或赋值t                         解释
----------------------------------------
  ==            匹配              相等比较
  !=             匹配              不等比较
  =              赋值              分配一个特定的值给该键,他可以覆盖之前的赋值。
  +=            赋值               追加特定的值给已经存在的键
  :=             赋值                分配一个特定的值给该键,后面的规则不可能覆盖它。

这有点类似我们常见的编程语言,比如C语言。只是这里的键一次可以处理多个值。有一些键在udev规则文件里经常出现,这些键的值可以使用通配符(*,?,甚至范围,比如[0-9]),这些常用键列举如下:

常用udev键
键                                                     含义
ACTION                  一个时间活动的名字,比如add,当设备增加的时候
KERNEL               在内核里看到的设备名字,比如sd*表示任意SCSI磁盘设备
DEVPATH             内核设备录进,比如/devices/*
SUBSYSTEM       子系统名字,比如sound,net
BUS                      总线的名字,比如IDE,USB
DRIVER               设备驱动的名字,比如ide-cdrom
ID                          独立于内核名字的设备名字
SYSFS{ value}     sysfs属性值,他可以表示任意
ENV{ key}             环境变量,可以表示任意
PROGRAM           可执行的外部程序,如果程序返回0值,该键则认为为真(true)
RESULT               上一个PROGRAM调用返回的标准输出。
NAME                     根据这个规则创建的设备文件的文件名。注意:仅仅第一行的NAME描述是有效的,后面的均忽略。
                                  如果你想使用使用两个以上的名字来访问一个设备的话,可以考虑SYMLINK键。

SYMLINK                 根据规则创建的字符连接名
OWNER                  设备文件的属组
GROUP                   设备文件所在的组。
MODE                      设备文件的权限,采用8进制
RUN                         为设备而执行的程序列表
LABEL                     在配置文件里为内部控制而采用的名字标签(下下面的GOTO服务)
GOTO                       跳到匹配的规则(通过LABEL来标识),有点类似程序语言中的GOTO
IMPORT{ type}        导入一个文件或者一个程序执行后而生成的规则集到当前文件
WAIT_FOR_SYSFS   等待一个特定的设备文件的创建。主要是用作时序和依赖问题。
PTIONS                     特定的选项: last_rule 对这类设备终端规则执行; ignore_device 忽略当前规则; ignore_remove 忽略接下来的并移走请求。all_partitions  为所有的磁盘分区创建设备文件。

3.udev配置项示例

给出一个列子来解释如何使用这些键。下面的例子来自Fedora Core 5系统的标准配置文件。

KERNEL=="*", OWNER="root" GROUP="root", MODE="0600"
KERNEL=="tty", NAME="%k", GROUP="tty", MODE="0666", OPTIONS="last_rule"
KERNEL=="scd[0-9]*", SYMLINK+="cdrom cdrom-%k"
KERNEL=="hd[a-z]", BUS=="ide", SYSFS{removable}=="1", SYSFS{device/media}=="cdrom", SYMLINK+="cdrom cdrom-%k"
ACTION=="add", SUBSYSTEM=="scsi_device", RUN+="/sbin/modprobe sg"

上面的例子给出了5个规则,每一个都是KERNEL或者ACTION键开头:

*第一个规则是缺省的,他匹配任意被内核识别到的设备,然后设定这些设备的属组是root,组是root,访问权限模式是0600(-rw-------)。这也是一个安全的缺省设置保证所有的设备在默认情况下只有root可以读写。
*第二个规则也是比较典型的规则了。它匹配终端设备(tty),然后设置新的权限为0600,所在的组是tty。它也设置了一个特别的设备文件名:%K。在这里例子里,%k代表设备的内核名字。那也就意味着内核识别出这些设备是什么名字,就创建什么样的设备文件名。

*第三行开始的KERNEL=="scd[0-9]*",表示 SCSI CD-ROM 驱动. 它创建一对设备符号连接:cdrom和cdrom-%k。

*第四行,开始的 KERNEL=="hd[a-z]", 表示ATA CDROM驱动器。这个规则创建和上面的规则相同的符号连接。ATA CDROM驱动器需要sysfs值以来区别别的ATA设备,因为SCSI CDROM可以被内核唯一识别。.

*第五行以 ACTION=="add"开始,它告诉udev增加 /sbin/modprobe sg 到命令列表,当任意SCSI设备增加到系统后,这些命令将执行。其效果就是计算机应该会增加sg内核模块来侦测新的SCSI设备。

当然,上面仅仅是一小部分例子,如果你的系统采用了udev方式,那你应该可以看到更多的规则。如果你想修改设备的权限或者创建信的符号连接,那么你需要熟读这些规则,特别是要仔细注意你修改的那些与之相关的设备。

4.修改你的udev配置

在修改udev配置之前,我们一定要仔细,通常的考虑是:你最好不要修改系统预置的那些规则,特别不要指定影响非常广泛的配置,比如上面例子中的第一行。不正确的配置可能会导致严重的系统问题或者系统根本就无法这个正确的访问设备。

而 我们正确的做法应该是在/etc/udev/rules.d/下创建一个信的规则文件。确定你给出的文件的后缀是rules文件名给出的数字序列应该比标 准配置文件高。比如,你可以创建一个名为99-my-udev.rules的规则文件。在你的规则文件中,你可以指定任何你想修改的配置,比如,假设你修 改修改floppy设备的所在组,还准备创建一个信的符号连接/dev/floppy,那你可以这么写:
KERNEL=="fd[0-9]*", GROUP="users",   SYMLINK+="floppy"

有些发行版本,比如Fedora,采用了外部脚本来修改某些特定设备的属组,组关系和权限。因此上面的改动可能并不见得生效。如果你遇到了这个问题,你就需要跟踪和修改这个脚本来达到你的目的。或者你可以修改PROGRAM或RUN键的值来做到这点。

某些规则的修改可能需要更深的挖掘。比如,你可能想在一个设备上使用sysfs信息来唯一标识一个设备。这些信息最好通过udevinfo命令来获取。
$ udevinfo –a –p $(udevinfo –q path  –n /dev/hda)

上 面的命令两次使用udevinfo:一次是返回sysfs设备路径(他通常和我们看到的Linux设备文件名所在路径--/dev/hda--不同);第 二次才是查询这个设备路径,结果将是非常常的syfs信息汇总。你可以找到最够的信息来唯一标志你的设备,你可以采用适当的替换udev配置文件中的 SYSFS选项。下面的结果就是上面的命令输出

[root@localhost rules.d]# udevinfo -a -p $(udevinfo -q path    -n  /dev/hda1)

Udevinfo starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

 looking at device '/block/hda/hda1':
   KERNEL=="hda1"
   SUBSYSTEM=="block"
   DRIVER==""
   ATTR{stat}=="    1133     2268        2        4"
   ATTR{size}=="208782"
   ATTR{start}=="63"
   ATTR{dev}=="3:1"

 looking at parent device '/block/hda':
   KERNELS=="hda"
   SUBSYSTEMS=="block"
   DRIVERS==""
   ATTRS{stat}=="   28905    18814  1234781   302540    34087   133247   849708   981336        0   218340  1283968"
   ATTRS{size}=="117210240"
   ATTRS{removable}=="0"
   ATTRS{range}=="64"
   ATTRS{dev}=="3:0"

 looking at parent device '/devices/pci0000:00/0000:00:1f.1/ide0/0.0':
   KERNELS=="0.0"
   SUBSYSTEMS=="ide"
   DRIVERS=="ide-disk"
   ATTRS{modalias}=="ide:m-disk"
   ATTRS{drivename}=="hda"
   ATTRS{media}=="disk"

 looking at parent device '/devices/pci0000:00/0000:00:1f.1/ide0':
   KERNELS=="ide0"
   SUBSYSTEMS==""
   DRIVERS==""

 looking at parent device '/devices/pci0000:00/0000:00:1f.1':
   KERNELS=="0000:00:1f.1"
   SUBSYSTEMS=="pci"
   DRIVERS=="PIIX_IDE"
   ATTRS{broken_parity_status}=="0"
   ATTRS{enable}=="1"
   ATTRS{modalias}=="pci:v00008086d000024CAsv0000144Dsd0000C009bc01sc01i8a"
   ATTRS{local_cpus}=="1"
   ATTRS{irq}=="11"
   ATTRS{class}=="0x01018a"
   ATTRS{subsystem_device}=="0xc009"
   ATTRS{subsystem_vendor}=="0x144d"
   ATTRS{device}=="0x24ca"
   ATTRS{vendor}=="0x8086"

 looking at parent device '/devices/pci0000:00':
   KERNELS=="pci0000:00"
   SUBSYSTEMS==""
   DRIVERS==""

举 一个例子:假设你想修改USB扫描仪的配置。通过一系列的尝试,你已经为这个扫描仪标识了Linux设备文件(每次打开扫描仪时,名字都会变)。你可以使 用上面的命令替换这个正确的Linux设备文件名,然后定位输出的采用SYSFS{idVendor}行和SYSFS{idProduct}行。最后你可 以使用这些信息来为这个扫描仪创建新的选项。

SYSFS{idVendor}=="0686", \

SYSFS{idProduct}=="400e", \

SYMLINK+="scanner", MODE="0664", \

group="scanner"

上面的例子表示将扫描仪的组设置为scanner,访问权限设置为0664,同时创建一个/dev/scanner的符号连接。

===================================================================================================================================

5.FAQ
问:什么是udev?
答:udev是一种工具,它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/dev目录下就只包含系统中真正存在的设备。

问:udev支持什么内核?
答:udev只支持linux-2.6内核,因为udev严重依赖于sysfs文件系统提供的信息,而sysfs文件系统只在linux-2.6内核中才有。

问:udev是一个内核程序还是用户程序?
答:udev是一个用户程序(user-mode daemon)。

问:udev和devfs有什么差别?
答:udev能够实现所有devfs实现的功能。但udev运行在用户模式中,而devfs运行在内核中。据称:devfs具有一些不太容易解决的先天缺陷。

问:udev的配置文件放在哪里?
答:udev是一个用户模式程序。它的配置文件是/etc/udev/udev.conf。这个文件一般缺省有这样几项:
udev_root="/dev" ; udev产生的设备文件的根目录是/dev
udev_db="/dev/.udevdb" ; 通过udev产生的设备文件形成的数据库
udev_rules="/etc/udev/rules.d" ;用于指导udev工作的规则所在目录。
udev_log="err" ;当出现错误时,用syslog记录错误信息。
 
问:udev的工作过程是怎样的?
答:由于没有研究过udev的源程序,不敢贸然就说udev的工作过程。我只是通过一些网上的资料和udev的说明文档,大致猜测它的工作过程可能是这样的。

当内核检测到在系统中出现了新设备后,内核会在sysfs文件系统中为该新设备生成一项新的记录,一般sysfs文件系统会被mount到/sys目录中。

新记录是以一个或多个文件或目录的方式来表示。每个文件都包含有特定的信息。(信息是如何表述的,还要另外研究?) udev在系统中是以守护进程的

方式udevd在运行,它通过某种途径(到底什么途径,目前还没搞懂。)检测到新设备的出现,通过查找设备对应的sysfs中的记录得到设备的一些信息。

udev会根据/etc/udev/udev.conf文件中的udev_rules指定的目录,逐个检查该目录下的文件,这个目录下的文件都是针对某类或某个设备应该施行什么

措施的规则文件。udev读取文件是按照文件名的ASCII字母顺序来读取的,如果udev一旦找到了与新加入的设备匹配的规则,udev就会根据规则定义

的措施对新设备进行配置。同时不再读后续的规则文件。

问:udev的规则文件的语法是怎样的?
答:udev的规则文件以行为单位,以"#"开头的行代表注释行。其余的每一行代表一个规则。每个规则分成一个或多个“匹配”和“赋值”部分。“匹配”部
分用“匹配“专用的关键字来表示,相应的“赋值”部分用“赋值”专用的关键字来表示。“匹配”关键字包括:ACTION,KERNEL,BUS,
SYSFS等等,“赋值”关键字包括:NAME,SYMLINK,OWNER等等。具体详细的描述可以阅读udev的man文档。
    下面举个例子来说明一下,

有这样一条规则:SUBSYSTEM=="net", ACTION=="add", SYSFS{address}=="00:0d:87:f6:59:f3", IMPORT="/sbin/rename_netiface %k eth0"
    这个规则中的“匹配”部分有三项,分别是SUBSYSTEM,ACTION和SYSFS。而"赋值"部分有一项,是IMPORT。这个规则就是说,当系统
中出现的新硬件属于net子系统范畴,系统对该硬件采取的动作是加入这个硬件,且这个硬件在SYSFS文件系统中的“address”信息等于“00:
0d..."时,对这个硬件在udev层次施行的动作是调用外部程序/sbin/rename_netiface,传递的参数有两个,一个是“%k”,代
表 内核对该新设备定义的名称。另一个是”eth0“。    从上面这个例子中可以看出,udev的规则的写法比较灵活的,尤其在“匹配”部分中,

可以通过诸如”*“, ”?“,[a-c],[1-9]等shell通配符来灵活匹配多个匹配项。具体的语法可以参考udev的man文档。

问:udev怎样做到不管设备连接的顺序而维持一个统一的设备名?
答:实际上,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等都不用修改。
问:怎样才能找到这些设备信息,并把他们放到udev的规则文件中来匹配呢?
答:这个问题比较难,网上资料不多,我只找到一篇文章来介绍如何写udev的规则。他的基本方法是通过udevinfo这个实用程序来找到那些可以作为规
则文件里的匹配项的项目。有这样两种情况可以使用这个工具:
    第一种情况是,当你把设备插入系统后,系统为设备产生了设备名(如/dev/sda)。那样的
话,你先用udevinfo -q path -n
/dev/sda,命令会产生一个该设备名对应的在sysfs下的路径,如/block/sda。然后,你再用udevinfo -a -p
/sys/block/sda,这个命令会显示一堆信息,信息分成很多块。这些信息实际来自于操作系统维护的sysfs链表,不同的块对应不同的路径。你
就可以用这些信息来作为udev规则文件中的匹配项。但需要注意的是,同一个规则只能使用同一块中显示的信息,不能跨块书写规则。
    第二种情况是,不知道系统产生的设备名,那就只有到/sys目录下去逐个目录查找了,反复用udevinfo
-a -p
/sys/path...这个命令看信息,如果对应的信息是这个设备的,那就恭喜你。否则就再换个目录。当然,在这种情况下,成功的可能性比较小。

抱歉!评论已关闭.