udev
一、概述
1. 为什么要使用udev
l 1. 系统通过卷标的功能来实现识别这个设备。而在集群的环境里面,不可能再使用卷标来识别设备的唯一性。应用程序不可能直接挂载卷标,而/etc/fstab可以通过卷标来挂载设备。(有些应用程序也没有办法识别卷标)。
l 2. 为什么要使用udev机制,因为当我们在做前方集群,不同机器挂载后方的存储,有可能不同的机器所识别出的名字不同,则造成设备的不唯一性。
l 3. 当系统读到rc.sysinit这个脚本的时候开始激活udev机制。
2. udev监控:#udevmonitor
l [root@localhost ~]#ls /dev/sdb #未插入U盘时
ls: /dev/sdb: 没有那个文件或目录
l [root@localhost ~]#udevmonitor #插入U盘,通过udevmonitor监控
udevmonitor prints the received event from the kernel [UEVENT]
and the event which udev sends out after rule processing [UDEV]
UEVENT[1316403060.858053] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1
UEVENT[1316403060.858856] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/usbdev1.4_ep00
UEVENT[1316403060.859400] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0
UEVENT[1316403060.860661] add@/class/scsi_host/host3
UEVENT[1316403060.862507] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/usbdev1.4_ep81
UEVENT[1316403060.862816] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/usbdev1.4_ep02
UEVENT[1316403060.863135] add@/class/usb_device/usbdev1.4
UDEV [1316403060.864574] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1
UDEV [1316403060.901102] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/usbdev1.4_ep00
UDEV [1316403060.929950] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0
UDEV [1316403060.949849] add@/class/scsi_host/host3
UDEV [1316403060.965811] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/usbdev1.4_ep81
UDEV [1316403060.976979] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/usbdev1.4_ep02
UDEV [1316403060.991296] add@/class/usb_device/usbdev1.4
UEVENT[1316403067.887071] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/host3/target3:0:0/3:0:0:0
UEVENT[1316403067.887106] add@/class/scsi_disk/3:0:0:0
UEVENT[1316403067.906185] add@/block/sdb
UEVENT[1316403067.906219] add@/block/sdb/sdb4
UEVENT[1316403067.906230] add@/class/scsi_device/3:0:0:0
UEVENT[1316403067.906239] add@/class/scsi_generic/sg1
UDEV [1316403067.913648] add@/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/host3/target3:0:0/3:0:0:0
UDEV [1316403067.933016] add@/class/scsi_disk/3:0:0:0
UDEV [1316403067.949991] add@/block/sdb
UDEV [1316403067.992497] add@/class/scsi_device/3:0:0:0
UDEV [1316403067.998881] add@/class/scsi_generic/sg1
UDEV [1316403068.040513] add@/block/sdb/sdb4
l [root@localhost ~]#ll /dev/sdb
brw-r----- 1 root disk 8, 16 09-19 11:31 /dev/sdb
#找到U盘,当再次拔出:则设备/dev/sdb也会消失。这就是udev机制。
3. /sys/和/proc/目录区别:
l 1. /sys/ :这个目录就是用来显示设备的状态的目录(文件类型),/sys/是根据不同设备架构进行分类的,并且可以做一些调优
l 2. /proc/ :也能显示设备的状态,/proc/一般只是进行查看。
4. udev功能
l 1. 动态管理:当设备添加/删除时,udev 的守护进程侦听来自内核的 uevent,以此添加或者删除/dev下的设备文件,所以udev只为已经连接的设备产生设备文件,而不会在/dev下产生大量虚无的设备文件。
l 2. 提供设备持续名称不变的能力
l 3. 使用相关用户程序来查询设备的名称
l 4. 编辑设备名称策略到内核中
l 5. 即可遵循LSB设备名称标准也可自定义设备名称(LSB:linux设备名称标准化)
l 6. udev消耗系统资源小
l 7. udev不关心设备主/辅设备号
5. udev工作过程
当一个设备添加/移除的时候,这时候udev就会做一下事情:
l 1. 读取/etc/udev/rules.d中策略文件
l 2. 执行策略中的命令
l 3. 将信息输出到/sys/中
二、Udev配置
1. udev的全局配置文件(/etc/udev/udev.conf)
[root@station55 ~]# vim /etc/udev/udev.conf
# udev.conf
# The initial syslog(3) priority: "err", "info", "debug" or its
# numerical equivalent. For runtime debugging, the daemons internal
# state can be changed with: "udevcontrol log_priority=<value>".
udev_log="err"
#日志的级别
udev_root = "/dev"
#将设备文件存放位置,一般都是放在/dev下的
udev_rules = "/etc/udev/rules.d/"
#udev策略存放位置,默认/etc/udev/rules.d/
2. udev策略文件
l 1 .策略文件格式:/etc/udev/rules.d/<rule_name>.rules
eg:99-myusb.rules
#必须".rules结尾";序号不能超过100,最好写99,序号越大,udev读取时间越晚,这样序号大的会覆盖序号小的策略。
l 2. 策略格式:<match-key><op>value [, ...] <assignment-key><op>value [, ...]
eg:BUS=="usb", SYSFS{serial}=="20043512321411d34721", NAME="usb_backup"
#== 代表:如果是
3. 查询udev匹配key value
l 1. cat /proc/bus/{usb,pci,...}/devices
l 2. #udevinfo -a -p $(udevinfo -q path -n /dev/sda)
#-a:产看所有属性,(/sys/下)
#-p:路径
eg:
[root@station5 ~]# udevinfo -a -p $(udevinfo -q path -n /dev/sdb)
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/sdb':
KERNEL=="sdb"
SUBSYSTEM=="block"
SYSFS{stat}==" 29 228 607 58 0 0 0 0 0 58 58"
SYSFS{size}=="15701759"
SYSFS{removable}=="1"
SYSFS{range}=="16"
SYSFS{dev}=="8:16"
looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/host1/target1:0:0/1:0:0:0':
ID=="1:0:0:0"
BUS=="scsi"
DRIVER=="sd"
SYSFS{ioerr_cnt}=="0x0"
SYSFS{iodone_cnt}=="0xd7"
SYSFS{iorequest_cnt}=="0xd7"
SYSFS{iocounterbits}=="32"
SYSFS{timeout}=="180"
SYSFS{state}=="running"
SYSFS{rev}=="8.01"
SYSFS{model}=="Cruzer "
SYSFS{vendor}=="SanDisk "
SYSFS{scsi_level}=="3"
SYSFS{type}=="0"
SYSFS{queue_type}=="none"
SYSFS{queue_depth}=="1"
SYSFS{device_blocked}=="0"
SYSFS{max_sectors}=="240"
looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/host1/target1:0:0':
ID=="target1:0:0"
BUS==""
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0/host1':
ID=="host1"
BUS==""
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1/1-1:1.0':
ID=="1-1:1.0"
BUS=="usb"
DRIVER=="usb-storage"
SYSFS{modalias}=="usb:v0781p5151d0200dc00dsc00dp00ic08isc06ip50"
SYSFS{bInterfaceProtocol}=="50"
SYSFS{bInterfaceSubClass}=="06"
SYSFS{bInterfaceClass}=="08"
SYSFS{bNumEndpoints}=="02"
SYSFS{bAlternateSetting}==" 0"
SYSFS{bInterfaceNumber}=="00"
looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1/1-1':
ID=="1-1"
BUS=="usb"
DRIVER=="usb"
SYSFS{configuration}==""
SYSFS{serial}=="026680028451965C"
SYSFS{product}=="Cruzer Micro"
SYSFS{manufacturer}=="SanDisk"
SYSFS{maxchild}=="0"
SYSFS{version}==" 2.00"
SYSFS{devnum}=="2"
SYSFS{speed}=="480"
SYSFS{bMaxPacketSize0}=="64"
SYSFS{bNumConfigurations}=="1"
SYSFS{bDeviceProtocol}=="00"
SYSFS{bDeviceSubClass}=="00"
SYSFS{bDeviceClass}=="00"
SYSFS{bcdDevice}=="0200"
SYSFS{idProduct}=="5151"
SYSFS{idVendor}=="0781"
SYSFS{bMaxPower}=="200mA"
SYSFS{bmAttributes}=="80"
SYSFS{bConfigurationValue}=="1"
SYSFS{bNumInterfaces}==" 1"
looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:03.0/usb1':
ID=="usb1"
BUS=="usb"
DRIVER=="usb"
SYSFS{configuration}==""
SYSFS{serial}=="0000:02:03.0"
SYSFS{product}=="EHCI Host Controller"
SYSFS{manufacturer}=="Linux 2.6.18-194.el5 ehci_hcd"
SYSFS{maxchild}=="6"
SYSFS{version}==" 2.00"
SYSFS{devnum}=="1"
SYSFS{speed}=="480"
SYSFS{bMaxPacketSize0}=="64"
SYSFS{bNumConfigurations}=="1"
SYSFS{bDeviceProtocol}=="01"
SYSFS{bDeviceSubClass}=="00"
SYSFS{bDeviceClass}=="09"
SYSFS{bcdDevice}=="0206"
SYSFS{idProduct}=="0000"
SYSFS{idVendor}=="0000"
SYSFS{bMaxPower}==" 0mA"
SYSFS{bmAttributes}=="e0"
SYSFS{bConfigurationValue}=="1"
SYSFS{bNumInterfaces}==" 1"
looking at parent device '/devices/pci0000:00/0000:00:11.0/0000:02:03.0':
ID=="0000:02:03.0"
BUS=="pci"
DRIVER=="ehci_hcd"
SYSFS{broken_parity_status}=="0"
SYSFS{enable}=="1"
SYSFS{modalias}=="pci:v000015ADd00000770sv000015ADsd00000770bc0Csc03i20"
SYSFS{local_cpus}=="ffffffff"
SYSFS{irq}=="51"
SYSFS{class}=="0x0c0320"
SYSFS{subsystem_device}=="0x0770"
SYSFS{subsystem_vendor}=="0x15ad"
SYSFS{device}=="0x0770"
SYSFS{vendor}=="0x15ad"
looking at parent device '/devices/pci0000:00/0000:00:11.0':
ID=="0000:00:11.0"
BUS=="pci"
DRIVER==""
SYSFS{broken_parity_status}=="0"
SYSFS{enable}=="1"
SYSFS{modalias}=="pci:v000015ADd00000790sv00000000sd00000000bc06sc04i01"
SYSFS{local_cpus}=="ffffffff"
SYSFS{irq}=="0"
SYSFS{class}=="0x060401"
SYSFS{subsystem_device}=="0x0000"
SYSFS{subsystem_vendor}=="0x0000"
SYSFS{device}=="0x0790"
SYSFS{vendor}=="0x15ad"
looking at parent device '/devices/pci0000:00':
ID=="pci0000:00"
BUS==""
DRIVER==""
[root@station5 ~]#vim /etc/udev/rules.d/99-myusb.rules
BUS=="usb",SYSFS{serial}=="026680028451965C",NAME="myusb"
#键值只要是能代表这个设备的唯一性就可以
[root@station5 ~]# ls /dev/myusb
/dev/myusb
#udev自动生成/dev/myusb设备
l 3. #scsi_id -g -x -s /block/sdN #scsi_id scsi设备信息参看工具
[root@station3 ~]# scsi_id -g -x -s /block/sda
ID_VENDOR=SEAGATE
ID_MODEL=ST973402SSUN72G
ID_REVISION=0603
ID_SERIAL=35000c5000b9c626f
ID_TYPE=disk
ID_BUS=scsi
#U盘或其他硬件设备使用udevinfo进行查询,硬盘和存储使用的scsi_id进行查询。
[root@station3 ~]#vim /etc/udev/rules.d/99-myusb.rules
PROGRAM=="/lib/udev/scsi_id -g -x -s /block/sda",RESULT=="ID_MODEL=ST973402SSUN72G,ID_SERIAL=35000c5000b9c626f",SYMLINK+="mydisk1"
#判断运行程序及其结果是否匹配,根据此结果给键赋值。
三、策略中各键值说明
1. 匹配键值
l == 是否等于
l != 不等于
eg:
ACTION=="add" #执行添加操作
KERNEL=="sa[a-z]1" #系统识别标识
BUS=="scsi" #总线类型为scsi
DRIVER!="ide-cdrom" #驱动不是ide-cdrom
SYSFS{serial}=="20043512321411d34721" #系统标识
PROGRAM=="custom_app.pl",RESULT=="some return string" #执行某一脚本或程序并返回值
#支持通配符*、?、[]、[a-z]、[!a]
2.给键分配键值
l = 给键赋值
l += 给键增加一个值,即给设备文件创建一个链接文件
l := 无法改变的赋值,后面的策略无法覆盖该值
eg:
NAME="usb_crypto"
SYMLINK+="data1"
OWNER="student"
MODE="0600"
LABEL="test_rules_end"
GOTO="test_rules_end"
RUN="myapp"
3. 实例
eg:
l [root@station5 ~]# vim /etc/udev/rules.d/99-myusb.rules
BUS=="usb",SYSFS{serial}=="026680028451965C",OWNER="netsword",GROUP="netsword",MODE="0600",NAME="myusb",RUN+="/tmp/test.sh"
#建议将创建设备改为创建软连接,即将NAME="myusb"改为SYMLINK+="myusb"
l [root@station5 ~]# vim /tmp/test.sh
#!/bin/bash
/usr/bin/wall hello
拔掉U盘,重新插入U盘
[root@station5 ~]#
Broadcast message from root (Wed Sep 21 10:37:41 2011):
hello
Broadcast message from root (Wed Sep 21 10:37:41 2011):
hello
Broadcast message from root (Wed Sep 21 10:37:41 2011):
hello
#出现以上信息,说明插入U盘后立即运行脚本/tmp/test/sh了
l [root@station5 ~]# ll /dev/myusb
brw------- 1 netsword netsword 8, 20 09-21 10:37 /dev/myusb
#U盘设备名宿主、权限等均按策略生成
4. udev rule example
egs:
l BUS=="scsi",SYSFS{serial}=="123456789",NAME="byLocation/rack1-disk3"
#在指定目录下创建设备文件,在/dev/下再创建一个byLocation目录
l KERNEL=="sd*",BUS=="scsi",PROGRAM=="/lib/udev/scsi_id -g -s %p",RESULT=="SATA ST340014AS3JX*LVCA",NAME="backup%n"
#PROGRAM中应用程序尽量使用绝对路径,其中的%p是设备号,和后面%n对应相同,如前面的p是1,那么后面的n就是1
lKERNEL=="sd*",SYSFS{idVendor}=="0781",SYSFS{idProduct}=="5150",SYMLINK+="keycard",OWNER="student",GROUP="student",MODE="0600"
#为设备创建软链接设备文件,并设置其宿主、权限,l KERNEL=="sd?1",BUS=="scsi",SYSFS{model}=="DSCT10",SYMLINK+="camera"
l ACTION=="add",KERNEL=="ppp0",RUN+="/usr/bin/wall ppp Interface Added"
#当系统新增加增加一个ppp0接口时,运行程序
l KERNEL=="ttyUSB*",BUS="usb",SYSFS{product}=="Palm Handheld",SYMLINK+="pda"
本文转自netsword 51CTO博客,原文链接:http://blog.51cto.com/netsword/670421