Linux下针对特定硬件外设锁定路径的方法

来源:互联网 发布:对外承包工程数据库 编辑:程序博客网 时间:2024/05/22 08:08

在Linux系统编程及嵌入式编程中,输入输出的基本方法就是读写访问/dev目录下的对应设备文件。例如,最常见的/dev/ttyUSBx设备对应于插入的USB-UART转接器;/dev/videox设备对应于摄像头设备。其中,设备名称结尾的x代指Linux内核为多个同种设备的编号id。实际工作中发现,Linux内核仅仅是按照发现设备的顺序从0开始依次编号,并不对设备号的顺序做出任何保证,并且在设备移除后,id保留一段时间后被新插入的设备复用。由于以上原因,即便是多次启动也可能带来对同一硬件设备的不同编号,故默认设备名不能固定,必须通过人为判断输入,给用户带来了麻烦。
其实,Linux系统已经内置针对这一问题的解决办法。


在目录/etc/udev/rules.d内,可以建立.rules文件,比如
/etc/udev/rules.d/50-udev.rules

加入语句

KERNEL=="hdb", NAME="my_disk"

匹配被内核命名为”hdb”的设备,重命名为 /dev/my_disk

KERNEL=="hdb", DRIVER=="ide-disk", SYMLINK+="sparedisk"

匹配被内核命名为”hdb”且驱动程序哦为”ide-disk”的设备,以默认名称命名,并创建一个符号链接/dev/sparedisk指向该设备

在规则中可以使用预设变量和通配符。比如:

  • 用%k表示设备名
KERNEL=="mice", NAME="input/%k"

会将/dev/mice设备转移到/dev/input/mice出现

  • 用%n表示设备编号
KERNEL=="loop0", NAME="loop/%n", SYMLINK+="%k"

会将/dev/loop设备转移到/dev/loop/0,并在/dev/loop0创建一个符号链接

  • 常用通配符 * ? []
KERNEL=="fd[0-9]*", NAME="floppy/%n", SYMLINK+="%k"

匹配所有软盘设备,并转移到/dev/floppy文件夹下,以对应设备号命名,并在原位置创建符号链接

KERNEL=="hiddev*", NAME="usb/%k"

将所有以hiddev开头的设备移动到/dev/usb/文件夹内


理论上,这样能够解决相当一部分设备的重命名问题。但是,若计算机插入了多个同类设备,则这一方法无力区分。解决办法是利用SUBSYSTEM和ATTRS关键字,沿设备树向上搜索,找到每个设备独有的特征标识,并将其写到规则文件里。为了查看设备的特征标识,可以选用以下几个命令:

find /sys -name dev

在sys文件树中寻找dev设备节点路径

udevadm info  --name=/dev/ttyUSB1 --attribute-walk

udevinfo -a -p /sys/block/sda

搜索驱动树


几个例子

  • 打印机原名为 /dev/lp0
# udevinfo -a -p $(udevinfo -q path -n /dev/lp0)  looking at device '/class/usb/lp0':    KERNEL=="lp0"    SUBSYSTEM=="usb"    DRIVER==""    ATTR{dev}=="180:0"  looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb1/1-1':    SUBSYSTEMS=="usb"    ATTRS{manufacturer}=="EPSON"    ATTRS{product}=="USB Printer"    ATTRS{serial}=="L72010011070626380"

其中有特征标识serial=”L72010011070626380”,故写

SUBSYSTEM=="usb", ATTRS{serial}=="L72010011070626380", SYMLINK+="epson_680"

  • USB Palm Pilot
    原名为/dev/ttyUSB1,规则写为
SUBSYSTEMS=="usb", ATTRS{product}=="Palm Handheld", KERNEL=="ttyUSB*", SYMLINK+="pilot"

依次匹配usb设备,生产商Palm Handheld,设备类型ttyUSB


  • USB摄像头
    摄像头有时会被辨认为单个分区的磁盘设备,比如/dev/sdb /dev/sdb1
#udevinfo -a -p $(udevinfo -q path -n /dev/sdb1)  looking at device '/block/sdb/sdb1':    KERNEL=="sdb1"    SUBSYSTEM=="block"  looking at parent device '/devices/pci0000:00/0000:00:02.1/usb1/1-1/1-1:1.0/host6/target6:0:0/6:0:0:0':    KERNELS=="6:0:0:0"    SUBSYSTEMS=="scsi"    DRIVERS=="sd"    ATTRS{rev}=="1.00"    ATTRS{model}=="X250,D560Z,C350Z"    ATTRS{vendor}=="OLYMPUS "    ATTRS{scsi_level}=="3"    ATTRS{type}=="0"

我们只需要用/dev/sdb1,但是由于驱动树的关系,所有匹配sdb1的特征也会匹配sdb。为了区分,还需要对应设备名进行匹配:

KERNEL=="sd?1", SUBSYSTEMS=="scsi", ATTRS{model}=="X250,D560Z,C350Z", SYMLINK+="camera"

  • USB硬盘
KERNEL=="sd*", SUBSYSTEMS=="scsi", ATTRS{model}=="USB 2.0 Storage Device", SYMLINK+="usbhd%n"

这个规则不会改变原设备名,而会创建以下符号链接
/dev/usbhd - 可用fdisk分区的节点
/dev/usbhd1 - 第一分区
/dev/usbhd2 - 第二分区

参考原文:
http://www.reactivated.net/writing_udev_rules.html

0 0
原创粉丝点击