分类: BSD
2008-03-20 16:51:14
eric.siroh(AT)gmail.com
FreeBSD-6之后,采用devfs管理,设备名称在设备联机时动态创建,增加了灵活性。但也带来另一些问题:一些外部设备,如、 PCCard等设备并不总是在开机之前就连接到计算机,如果存在相同类型的设备,这些设备的在/dev的节点名称会因为设备连接到计算机的先后顺序而发生 变化,这会给一些应用程序的设置造成一些不便。然而,正是因为devfs的灵活性,也带来很好的方法来支持这些外部设备使用固定设备节点名称。
这里通过两台USB接口打印机EPSON Stylus CX3700、Brother FAX-2820的设置来说明这一方法。
首先,查看/etc/devd.conf文件,确定有关的基本配置情况
#more /etc/devd.conf
...
options {
# Each directory directive adds a directory the list of directories
# that we scan for files. Files are read-in in the order that they
# are returned from readdir(3). The rule-sets are combined to
# create a DFA that's used to match events to actions.
directory "/etc/devd";
directory "/usr/local/etc/devd";
pid-file "/var/run/devd.pid";
# Setup some shorthand for regex that we use later in the file.
#XXX Yes, these are gross -- imp
set scsi-controller-regex
"(aac|adv|adw|aha|ahb|ahc|ahd|aic|amd|amr|asr|bt|ciss|ct|dpt|\
esp|ida|iir|ips|isp|mlx|mly|mpt|ncr|ncv|nsp|stg|sym|trm|wds)\
[0-9]+";
};
...
通过这两行:
directory "/etc/devd";
directory "/usr/local/etc/devd";
得知用户定制配置文件目录为/etc/devd,/usr/local/etc/devd。如果没有相应的目录,自行建立就可以了。当然也可以自行修改,不过不建议修改。
在编写配置文件之前,需要得到设备的必要参数。可以通过在前台运行调试模式的devd来查看。现在不要连接设备,运行
#/etc/rc.d/devd stop
#/sbin/devd -Dd
屏幕上会出现一些信息,表明devd已经运行了。这时把设备连接到计算机,然后再拔掉设备。这个过程中屏幕会有很多输出,只需要查看以Processing event开头信息。以下两行示例是U盘的插拔发生的信息。
Processing event '+umass0 vendor=0x1043 product=0x8012 devclass=0x00 devsubclass=0x00 =0x0100 sernum="" intclass=0x08 intsubclass=0x06 at port=1 interface=0 vendor=0x1043 product=0x8012 devclass=0x00 devsubclass=0x00 release=0x0100 sernum="" intclass=0x08 intsubclass=0x06 on uhub1'
Processing event '-umass0 vendor=0x1043 product=0x8012 devclass=0x00 devsubclass=0x00 release=0x0100 sernum="" intclass=0x08 intsubclass=0x06 at port=1 interface=0 vendor=0x1043 product=0x8012 devclass=0x00 devsubclass=0x00 release=0x0100 sernum="" intclass=0x08 intsubclass=0x06 on uhub1'
umass0是devfs为U盘在/dev下自动生成的设备节点,+umass0表示umass0连接上计算机了,-umass0表示umass0设备被拔出。
我们需要得到设备信息主要是vendor,product,sernum三个参数。vendor是制造商的代码,product是设备型号代码,sernum是设备的序列好,这三个参数基本上应该可以确定唯一一台设备。
如果没有多于一台同一厂家同一型号(或同一系列,有点厂家设备虽然标识的型号不同,但是product值却是一样的)的设备,实际应用中 vendor和product也就可以确定不同的设备了,这里还是使用sernum来增加确定性。在上面的示例中sernum为空,说明有的U盘没有序列 号,没有序列号的U盘,不能用这三个参数来唯一确定。对于U盘可以通过glabel加标签的方法标识不同的U盘,会更方便一些。
获得必要的设备信息之后,就可以在控制台按Ctrl+C退出devd进程。
本例当中的两台USB打印机通过上述方法得到有关参数分别如下:
EPSON Stylus CX3700 product 0x0818 vendor 0x04b8 sernum L34020604060324210
Brother FAX-2820 product 0x0187 vendor 0x04f9 sernum 000H5J658204
得到上述的这些信息之后,就可以动手编写配置文件了,配置文件应该保存在/etc/devd.conf文件中指定的目录下,本例中为/etc/devd/ulpt.conf,内容如下:
# EPSON Stylus CX3700 printer
# product 0x0818
# vendor 0x04b8
# sernum L34020604060324210
attach 100 { # 定义设备连接时的动作。100为优先级,用来控制
# 配置文件中该设备其他可能动作的先后次序
device-name "ulpt[0-9]+"; # 检测设备名称
match "product" "0x0818"; # 检测product
match "vendor" "0x04b8"; # 检测vendor
match "sernum" "L34020604060324210"; # 检测sernum
action "/bin/ln -sf /dev/$device-name /dev/epPRN"; # 如果该设备符合上面三个条件,
# 那么就在创建一个指向实际设备名的指定名称连接
};
# Brother FAX-2820 printer
# product 0x0187
# vendor 0x04f9
# sernum 000H5J658204
attach 100 {
match "product" "0x0187";
match "vendor" "0x04f9";
match "sernum" "000H5J658204";
action "/bin/ln -sf /dev/$device-name /dev/brPRN";
};
# For detach USB printer
detach 100 { # 定义设备拔出时的动作
device-name "ulpt[0-9]+";
# 当设备拔除时,删除相应的连接
action "/bin/rm /dev/`/bin/ls -l /dev | /usr/bin/awk '/^l.*$device-name\$/{print \$9}'`";
};
在上面的示例文件生效后,当EPSON Stylus CX3700联机时,devd服务进程就会根据配置文件指定的条件,创建一个指向自动分配给这个的节点的名为/dev/epPRN的连接。对于 Brother FAX-2820,则创建/dev/brPRN的连接。
这样,无论两台是单独联机还是同时联机,也不管两台打印机联机的先后次序,/dev/epPRN总是指向为EPSON Stylus CX3700创建的设备节点,而/dev/brPRN总是指向为Brother FAX-2820创建的设备节点。
保存配置文件后,重新启动devd服务,配置就可以生效了。
#/etc/rc.d/devd start
如果没有生效,再次前台运行调试模式的devd来查看有关信息排除错误。
经过这样的设置,在CUPS配置时就不用为设备节点名称不固定而头疼了,配置EPSON Stylus CX3700时,打印机URI使用usb:/dev/epPRN,而Brother FAX-2820则使用usb:/dev/brPRN。其他热插拔设备应当可以参照上述方法设置。