掌握udev

<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>

 如果你使用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創建的設備文 件。賦值鍵可以處理一個多值列表。匹配鍵和賦值鍵操作符解釋見下表:


                      udev 鍵/值對操作符
操作符     匹配或賦值t                         解釋
----------------------------------------
 ==            匹配              相等比較
 !=            匹配             不等比較
 =            賦值              分配一個特定的值給該鍵,他可以覆蓋之前的賦值。
 +=      賦值              追加特定的值給已經存在的鍵
 :=            賦值                  分配一個特定的值給該鍵,後面的規則不可能覆蓋它。


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


常用udev鍵
鍵        含義
ACTION         一個時間活動的名字,比如add,當設備增加的時候
KERNEL         在內核裏看到的設備名字,比如sd*表示任意SCSI磁盤設備
DEVPATH       內核設備錄進,比如/devices/*
SUBSYSTEM       子系統名字,比如sound,net
BUS         總線的名字,比如IDE,USB
DRIVER         設備驅動的名字,比如ide-cdrom
ID           獨立於內核名字的設備名字
SYSFS{ value}       sysfs屬性值,他可以表示任意
ENV{ key}       環境變量,可以表示任意
PROGRAM       可執行的外部程序,如果程序返回0值,該鍵則認爲爲真(true)
RESULT         上一個PROGRAM調用返回的標準輸出。
NAME         根據這個規則創建的設備文件的文件名。注意:僅僅第一行的NAME描述是有效的,後面的均忽略。
                                 如果你想使用使用兩個以上的名字來訪問一個設備的話,可以考慮SYMLINK鍵。
SYMLINK       根據規則創建的字符連接名
OWNER         設備文件的屬組
GROUP         設備文件所在的組。
MODE         設備文件的權限,採用8進制
RUN         爲設備而執行的程序列表
LABEL         在配置文件裏爲內部控制而採用的名字標籤(下下面的GOTO服務)
GOTO         跳到匹配的規則(通過LABEL來標識),有點類似程序語言中的GOTO
IMPORT{ type}     導入一個文件或者一個程序執行後而生成的規則集到當前文件
WAIT_FOR_SYSFS   等待一個特定的設備文件的創建。主要是用作時序和依賴問題。
PTIONS         特定的選項: last_rule 對這類設備終端規則執行; ignore_device 忽略當前規則; ignore_remove 忽略接下來的並移走請求。
           all_partitions 爲所有的磁盤分區創建設備文件。


我們給出一個列子來解釋如何使用這些鍵。下面的例子來自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"

<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"></script>


上面的例子給出了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選項。下面的結果就是上面的命令輸出


[root@localhost 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}=="0x8086"

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


----------------------------------------------------------------------------------------------------------------------------------

Udev (簡體中文)

From ArchWiki

Jump to: navigation, search


i18n
English
Русский
繁體中文
簡體中文

注意: 如果您是從DevFS升級到Udev, 請查看 DevFS to Udev.

這篇文檔將介紹udev的一些新的變化。從084版開始,udev能夠代替hotplug和coldplug的所有功能。正因爲這樣,hotplug包已經從Arch倉庫中去掉了。

Contents

[hide]

[edit] 重要提示

...切記,在使用udev加載任何modules(內核模塊)之前(無論是否是啓動時自動加載),您必須在/etc/rc.confMOD_AUTOLOAD選項設置爲yes ,否則您必須手動加載這些modules。您可以修改rc.conf中的MODULES或者使用modprobe命令來手動加載您所需要的modules。另一種方法是用hwdetect --modules生成系統硬件的modules列表,然後將這個列表添加到rc.conf中讓系統啓動時自動加載這些modules

[edit] 基本需求

  • 內核: 2.6.15或更高版本。
  • 您將無法在fstab和bootloader設置中再使用DevFS格式的設備名稱! 更多相關內容請查看DevFS to Udev

[edit] 最近更新

  • startudev程序被取出。如果需要重新加載udev規則請使用 /etc/start_udev
  • Udev代替了hotplughwdetect的功能。同時我們保存了hwdetect,並且只在 mkinitrd程序生成initrd的時候用到。
  • Udev可以同時加載多個模塊,這樣可以加快啓動速度,然而,這樣做的結果是她不能保證每次加載的順序,所以當你使用多聲卡或網卡的時候就會出現問題,這個問題下面將會再討論。

[edit] 模塊禁用列表

udev也會犯錯或加載錯誤的模塊。爲了防止錯誤的發生,你可以使用模塊禁用列表 。一旦加入該列表的模塊,無論是啓動時,或者時運行時(如usb硬盤等)udev都不會加載這些模塊。

只需在您在 rc.confMODULES中對應模塊前加上感嘆號(!)就可禁用該模塊。

例如,

MODULES=(!moduleA !moduleB)

[edit] load_modules: 有用的啓動參數

如果您在內核啓動參數中加入load_modules=off,那麼udev會停止任何自動加載工作. 如果系統出現問題時,這個功能會十分有用。如果udev加載了有問題的模塊導致系統掛起或者其它嚴重的問題時,你可以使用這個參數來禁用自動加載,以此來防止加載有問題的模塊。

[edit] 已知的硬件問題

- BusLogic設備被損壞而且導致啓動時死機。

 這是一個內核的Bug目前還沒有修正。

- PCMCIA讀卡器被認爲是可移除設備.

 把它們加入到/etc/pmount.allow中,使用hal的pmount來讀取

[edit] 自動加載帶來的一些問題

[edit] CPUFreq模塊

我門還沒有找到一個很好的方法加載不同的CPUFreq控制器,所以我們把從自動加載進程裏把它去掉了。如果您需要測量CPU頻率,你必須在rc.confMODULES隊列中顯式的加入合適的模塊。

[edit] 聲音問題和一些不能自動加載的模塊

一些用戶跟蹤發現問題出在/etc/modprobe.conf中一些舊的部分,試着去掉這些舊的部分再試試看。

[edit] 多個同類型設備(網卡,聲卡)每次啓動的都不同

因爲udev同時加載所有模塊,所以一些設備可能初始化順序不同。例如同時有兩個網卡時,它們總是在eth0eth1之間變來變去。

常用的解決辦法是在您的rc.conf文件中通過修改MODULES隊列來指明順序。這個隊列裏的模塊將在udev自動加載之前由系統加載,因此您可以控制模塊在啓動時加載順序。

# 在e100之前加載8139too
MODULES=(8139too e100)

另一個解決網卡的方法是使用udev-sanctified方法爲每個網卡靜態命名。創建文件/etc/udev/rules.d/10-network.rules然後將不同的網卡通過MAC地址綁定到不同的名字上:

SUBSYSTEM=="net", SYSFS{address}=="aa:bb:cc:dd:ee:ff", NAME="lan0"
SUBSYSTEM=="net", SYSFS{address}=="ff:ee:dd:cc:bb:aa", NAME="wlan0"

同時,您需要注意以下內容:

  • 您可以通過下面的命令獲得網卡的MAC地址:: udevinfo -a -p /sys/class/net/<你的網卡>
  • 注意在udev規則文件中使用小寫的16進制MAC地址,因爲udev無法識別大寫的MAC地址。
  • 一些用戶在使用舊的命名方式時出現問題,例如: eth0, eth1, 等等. 如果出現這個問題,試試使用 "lan"或者"wlan"之類的名字.

注意不要忘記修改您的/dec/rc.conf和其它使用ethX命名的配置文件。

[edit] 自己編譯內核造成的一些已知問題

[edit] Udev無法啓動

請確定您的內核版本大於或等於2.6.15。較早的內核沒有udev自動裝載所需要的uevent功能。

[edit] CD/DVD符號和權限錯誤

如果您使用2.6.15的內核的話,您需要安裝ABS的uevent補丁(它從2.6.16內核中抽取了一些uevent功能)。您可以使用abs命令來同步ABS樹,然後您就可以在/var/abs/kernels/kernel26/下找到abs補丁。

[edit] Udev小竅門

[edit] 自動加載usb設備

KERNEL=="sd[a-z]", NAME="%k", SYMLINK+="usb%m", GROUP="users", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", SYMLINK+="usb%n", GROUP="users", NAME="%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mkdir -p /mnt/usb%n"
ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="vfat", RUN+="/bin/mount -t vfat -o rw,noauto,sync,dirsync,noexec,nodev,noatime,dmask=000,fmask=111 /dev/%k /mnt/usb%n", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mount -t auto -o rw,noauto,sync,dirsync,noexec,nodev,noatime /dev/%k /mnt/usb%n", OPTIONS="last_rule"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/umount -l /mnt/usb%n"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rmdir /mnt/usb%n", OPTIONS="last_rule"

把這些udev規則放到/etc/udev/rules.d/下任何一個文件名以.rules結尾的文件中,例如/etc/udev/rules.d/sda.rules。

如果想同時建立/media到/mnt符號連接,可以使用下面的版本:

KERNEL=="sd[a-z]", NAME="%k", SYMLINK+="usbhd-%k", GROUP="users", OPTIONS="last_rule" 
ACTION=="add", KERNEL=="sd[a-z][0-9]", SYMLINK+="usbhd-%k", GROUP="users", NAME="%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mkdir -p /media/usbhd-%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/ln -s /media/usbhd-%k /mnt/usbhd-%k"
ACTION=="add", KERNEL=="sd[a-z][0-9]", PROGRAM=="/lib/udev/vol_id -t %N", RESULT=="vfat", RUN+="/bin/mount -t vfat -o rw,noauto,sync,dirsync,noexec,nodev,noatime,dmask=000,fmask=111 /dev/%k /media/usbhd-%k", OPTIONS="last_rule"
ACTION=="add", KERNEL=="sd[a-z][0-9]", RUN+="/bin/mount -t auto -o rw,noauto,sync,dirsync,noexec,nodev,noatime /dev/%k /media/usbhd-%k", OPTIONS="last_rule"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rm -f /mnt/usbhd-%k"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/umount -l /media/usbhd-%k"
ACTION=="remove", KERNEL=="sd[a-z][0-9]", RUN+="/bin/rmdir /media/usbhd-%k", OPTIONS="last_rule"

注意!如果你是用的其它的固定設備(例如SATA的硬盤,您可以從/etc/fstab中查看)被識別爲/dev/sdX,您必須從sd[a-z] 中去掉你的那個sdX。例如,如果您的SATA硬盤被是識別爲/dev/sda,您就需要把所有的“sd[a-z]”替換成“sd[b-z]”。 在規則文件的文件名前加上數字(如:010.udev.rules)是個很好的主意,這樣udev在讀取標準規則前,將會讀取這個規則文件。 這些規則設置後不需要修改/etc/fstab文件。請查看mount命令的參數來修改權限等特性(您可以從論壇搜索查看mount命令的參數,然後根據 您的需要修改它們)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章