1. 程式人生 > >新增Udev規則,讓Linux自動掛載U盤(轉載)

新增Udev規則,讓Linux自動掛載U盤(轉載)

如果你使用Linux比較長時間了,那你就知道,在對待裝置檔案這塊,Linux改變了幾次策略。在Linux早期,裝置檔案僅僅是是一些帶有適當的屬性集的普通檔案,它由mknod命令建立,檔案存放在/dev目錄下。後來,採用了devfs,一個基於核心的動態裝置檔案系統,他首次出現在2.3.46核心中。Mandrake,Gentoo等Linux分發版本採用了這種方式。devfs建立的裝置檔案是動態的。但是devfs有一些嚴重的限制,從2.6.13版本後移走了。目前取代他的便是文字要提到的udev--一個使用者空間程式。

目前很多的Linux分發版本採納了udev的方式,因為它在Linux裝置訪問,特別是那些對裝置有極端需求的站點(比如需要控制上千個硬碟)和熱插拔裝置(比如USB攝像頭和MP3播放器)上解決了幾個問題。下面我我們來看看如何管理udev裝置。

實際上,對於那些為磁碟,終端裝置等準備的標準配置檔案而言,你不需要修改什麼。但是,你需要了解udev配置來使用新的或者外來裝置,如果不修改配置,這些裝置可能無法訪問,或者說Linux可能會採用不恰當的名字,屬組或許可權來建立這些裝置檔案。你可能也想知道如何修改RS-232串列埠,音訊裝置等檔案的屬組或者許可權。這點在實際的Linux實施中是會遇到的。


為什麼使用udev



在此之前的裝置檔案管理方法(靜態檔案和devfs)有幾個缺點:

*不確定的裝置對映。特別是那些動態裝置,比如USB裝置,裝置檔案到實際裝置的對映並不可靠和確定。舉一個例子:如果你有兩個USB印表機。一個可能稱為/dev/usb/lp0,另外一個便是/dev/usb/lp1。但是到底哪個是哪個並不清楚,lp0,lp1和實際的裝置沒有一一對應的關係,因為他可能因為發現裝置的順序,印表機本身關閉等原因而導致這種對映並不確定。理想的方式應該是:兩個印表機應該採用基於他們的序列號或者其他標識資訊的唯一裝置檔案來對映。但是靜態檔案和devfs都無法做到這點。

*沒有足夠的主/輔裝置號。我們知道,每一個裝置檔案是有兩個8位的數字:一個是主裝置號 ,另外一個是輔裝置號來分配的。這兩個8位的數字加上裝置型別(塊裝置或者字元裝置)來唯一標識一個裝置。不幸的是,關聯這些身邊的的數字並不足夠。

*/dev目錄下檔案太多。一個系統採用靜態裝置檔案關聯的方式,那麼這個目錄下的檔案必然是足夠多。而同時你又不知道在你的系統上到底有那些裝置檔案是啟用的。

*命名不夠靈活。儘管devfs解決了以前的一些問題,但是它自身又帶來了一些問題。其中一個就是命名不夠靈活;你別想非常簡單的就能修改裝置檔案的名字。預設的devfs命令機制本身也很奇怪,他需要修改大量的配置檔案和程式。;

*核心記憶體使用,devfs特有的另外一個問題是,作為核心驅動模組,devfs需要消耗大量的記憶體,特別當系統上有大量的裝置時(比如上面我們提到的系統一個上有好幾千磁碟時)

udev的目標是想解決上面提到的這些問題,他通採用使用者空間(user-space)工具來管理/dev/目錄樹,他和檔案系統分開。知道如何改變預設配置能讓你之大如何定製自己的系統,比如建立裝置字元連線,改變裝置檔案屬組,許可權等。

udev配置檔案


主要的udev配置檔案是/etc/udev/udev.conf。這個檔案通常很短,他可能只是包含幾行#開頭的註釋,然後有幾行選項:

udev_root=”/dev/”

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

udev_log=”err”

上面的第二行非常重要,因為他表示udev規則儲存的目錄,這個目錄儲存的是以.rules結束的檔案。每一個檔案處理一系列規則來幫助udev分配名字給裝置檔案以保證能被核心識別。 
你的/etc/udev/rules.d下面可能有好幾個udev規則檔案,這些檔案一部分是udev包安裝的,另外一部分則是可能是別的硬體或者軟體包生成的。比如在Fedora Core 5系統上,sane-backends包就會安裝60-libsane.rules檔案,另外initscripts包會安裝60-net.rules檔案。這些規則檔案的檔名通常是兩個數字開頭,它表示系統應用該規則的順序。

規則檔案裡的規則有一系列的鍵/值對組成,鍵/值對之間用逗號(,)分割。每一個鍵或者是使用者匹配鍵,或者是一個賦值鍵。匹配鍵確定規則是否被應用,而賦值鍵表示分配某值給該鍵。這些值將影響udev建立的裝置檔案。賦值鍵可以處理一個多值列表。匹配鍵和賦值鍵操作符解釋見下表:


這有點類似我們常見的程式語言,比如C語言。只是這裡的鍵一次可以處理多個值。有一些鍵在udev規則檔案裡經常出現,這些鍵的值可以使用萬用字元(*,?,甚至範圍,比如[0-9]),這些常用鍵列舉如下:


我們給出一個列子來解釋如何使用這些鍵。下面的例子來自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方式,那你應該可以看到更多的規則。如果你想修改裝置的許可權或者建立信的符號連線,那麼你需要熟讀這些規則,特別是要仔細注意你修改的那些與之相關的裝置。

修改你的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選項。下面的結果就是上面的命令輸出

[[email protected] 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}==”0×8086″

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的符號連線。

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

以下是一位網友的測試

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

參考文章:http://wiki.archlinux.org/index.php/Udev

http://mlsx.xplore.cn/read.php?666

http://blog.chinaunix.net/u/22153/showart_399658.html

新增一下內容到/etc/udev/rules.d/10-my-udev.rules裡

程式碼:

KERNEL=="sd[b-z]", NAME="%k", SYMLINK+="usbhd-%k", GROUP="users", OPTI 

ACTION=="add", KERNEL=="sd[b-z][0-9]", SYMLINK+="usbhd-%k", GROUP="users", NAME="%k" 

ACTION=="add", KERNEL=="sd[b-z][0-9]", RUN+="/bin/mkdir -p /media/usbhd-%k" 

ACTION=="add", KERNEL=="sd[b-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="vfat", RUN+="/bin/mount -t vfat -o rw,utf8=true,codepage=936,noauto,flush,quiet,nodev,nosuid,noexec,noatime,dmask=000,fmask=111 /dev/%k /media/usbhd-%k", OPTI 

ACTION=="add", KERNEL=="sd[b-z][0-9]", RUN+="/bin/mount -t auto -o rw,locale=zh_CN.UTF-8,noauto,sync,dirsync,noexec,nodev,noatime /dev/%k /media/usbhd-%k", OPTI 

ACTION=="remove", KERNEL=="sd[b-z][0-9]", RUN+="/bin/umount -l /media/usbhd-%k" 

ACTION=="remove", KERNEL=="sd[b-z][0-9]", RUN+="/bin/rm -rf /media/usbhd-%k", OPTI

然後sudo udevcontrol reload_rules就可以了。。

經測試支援自動掛載VFAT格式的U盤,並能正確顯示包含中文的檔名,其它檔案格式未測試。。預設掛載到/media/usbhd-sdb1資料夾上。。