FreeBSD使用固定设备节点名操作设备

使用固定设备节点名操作设备

eric.siroh(AT)gmail.com

FreeBSD-6之后,采用devfs管理设备节点,设备名称在设备联机时动态创建,增加了灵活性。但也带来另一些问题:一些外部设备,如USB、PCCard等设备并不总是在开机之前就连接到计算机,如果存在相同类型的设备,这些设备的在/dev的节点名称会因为设备连接到计算机的先后顺序而发生变化,这会给一些应用程序的设置造成一些不便。然而,正是因为devfs的灵活性,也带来很好的方法来支持这些外部设备使用固定设备节点名称。

这里通过两台USB接口打印机EPSON Stylus CX3700、Brother FAX-2820的设置来说明这一方法。

查看devfs基本配置

首先,查看/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 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’
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, For 6.x, 7.x
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的连接。

FreeBSD 8.x 以后,devd实现了在设备拔除时也能给出product、vendor、sernum等信息,这样拔除设备时删除连接的方式就不需要写一大串天书一样的代码(这样的代码用来炫耀还是不错的;P)

# For 8.x or later
detach 100 {
   match "product"      "0x0187";
   match "vendor"       "0x04f9";
   match "sernum"       "000H5J658204";
   action   "/bin/rm -f /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。其他热插拔设备应当可以参照上述方法设置。

原文链接:http://wiki.freebsdchina.org/doc/s/devfs