如果你使用Linux比較長(cháng)時(shí)間了,那你就知道,在對待設備文件這塊,Linux改變了幾次策略。在Linux早期,設備文件僅僅是是一些帶有適當的屬性集的普通文件,它由mknod命令創(chuàng )建,文件存放在/dev目錄下。后來(lái),采用了devfs,一個(gè)基于內核的動(dòng)態(tài)設備文件系統,他首次出現在2.3.46內核中。Mandrake,Gentoo等Linux分發(fā)版本采用了這種方式。devfs創(chuàng )建的設備文件是動(dòng)態(tài)的。但是devfs有一些嚴重的限制,從2.6.13版本后移走了。目前取代他的便是文本要提到的udev--一個(gè)用戶(hù)空間程序。 */dev目錄下文件太多。一個(gè)系統采用靜態(tài)設備文件關(guān)聯(lián)的方式,那么這個(gè)目錄下的文件必然是足夠多。而同時(shí)你又不知道在你的系統上到底有那些設備文件是激活的。 *命名不夠靈活。盡管devfs解決了以前的一些問(wèn)題,但是它自身又帶來(lái)了一些問(wèn)題。其中一個(gè)就是命名不夠靈活;你別想非常簡(jiǎn)單的就能修改設備文件的名字。缺省的devfs命令機制本身也很奇怪,他需要修改大量的配置文件和程序。; *內核內存使用,devfs特有的另外一個(gè)問(wèn)題是,作為內核驅動(dòng)模塊,devfs需要消耗大量的內存,特別當系統上有大量的設備時(shí)(比如上面我們提到的系統一個(gè)上有好幾千磁盤(pán)時(shí)) udev的目標是想解決上面提到的這些問(wèn)題,他通采用用戶(hù)空間(user-space)工具來(lái)管理/dev/目錄樹(shù),他和文件系統分開(kāi)。知道如何改變缺省配置能讓你之大如何定制自己的系統,比如創(chuàng )建設備字符連接,改變設備文件屬組,權限等。 udev配置文件 主要的udev配置文件是/etc/udev/udev.conf。這個(gè)文件通常很短,他可能只是包含幾行#開(kāi)頭的注釋?zhuān)缓笥袔仔羞x項: udev_root=”/dev/” udev_rules=”/etc/udev/rules.d/” udev_log=”err” 上面的第二行非常重要,因為他表示udev規則存儲的目錄,這個(gè)目錄存儲的是以.rules結束的文件。每一個(gè)文件處理一系列規則來(lái)幫助udev分配名字給設備文件以保證能被內核識別。 你的/etc/udev/rules.d下面可能有好幾個(gè)udev規則文件,這些文件一部分是udev包安裝的,另外一部分則是可能是別的硬件或者軟件包生成的。比如在Fedora Core5系統上,sane-backends包就會(huì )安裝60-libsane.rules文件,另外initscripts包會(huì )安裝60-net.rules文件。這些規則文件的文件名通常是兩個(gè)數字開(kāi)頭,它表示系統應用該規則的順序。 規則文件里的規則有一系列的鍵/值對組成,鍵/值對之間用逗號(,)分割。每一個(gè)鍵或者是用戶(hù)匹配鍵,或者是一個(gè)賦值鍵。匹配鍵確定規則是否被應用,而賦值鍵表示分配某值給該鍵。這些值將影響udev創(chuàng )建的設備文件。賦值鍵可以處理一個(gè)多值列表。匹配鍵和賦值鍵操作符解釋見(jiàn)下表: udev 鍵/值對操作符 操作符 匹配或賦值t 解釋 ---------------------------------------- == 匹配 相等比較 != 匹配 不等比較 = 賦值 分配一個(gè)特定的值給該鍵,他可以覆蓋之前的賦值。 += 賦值 追加特定的值給已經(jīng)存在的鍵 := 賦值 分配一個(gè)特定的值給該鍵,后面的規則不可能覆蓋它。 這有點(diǎn)類(lèi)似我們常見(jiàn)的編程語(yǔ)言,比如C語(yǔ)言。只是這里的鍵一次可以處理多個(gè)值。有一些鍵在udev規則文件里經(jīng)常出現,這些鍵的值可以使用通配符(*,?,甚至范圍,比如[0-9]),這些常用鍵列舉如下: 常用udev鍵 鍵 含義 ACTION 一個(gè)時(shí)間活動(dòng)的名字,比如add,當設備增加的時(shí)候 KERNEL 在內核里看到的設備名字,比如sd*表示任意SCSI磁盤(pán)設備 DEVPATH 內核設備錄進(jìn),比如/devices/* SUBSYSTEM 子系統名字,比如sound,net BUS 總線(xiàn)的名字,比如IDE,USB DRIVER 設備驅動(dòng)的名字,比如ide-cdrom ID 獨立于內核名字的設備名字 SYSFS{ value} sysfs屬性值,他可以表示任意 ENV{ key} 環(huán)境變量,可以表示任意 PROGRAM 可執行的外部程序,如果程序返回0值,該鍵則認為為真(true) RESULT 上一個(gè)PROGRAM調用返回的標準輸出。 NAME 根據這個(gè)規則創(chuàng )建的設備文件的文件名。注意:僅僅第一行的NAME描述是有效的,后面的均忽略。 如果你想使用使用兩個(gè)以上的名字來(lái)訪(fǎng)問(wèn)一個(gè)設備的話(huà),可以考慮SYMLINK鍵。 SYMLINK 根據規則創(chuàng )建的字符連接名 OWNER 設備文件的屬組 GROUP 設備文件所在的組。 MODE 設備文件的權限,采用8進(jìn)制 RUN 為設備而執行的程序列表 LABEL 在配置文件里為內部控制而采用的名字標簽(下下面的GOTO服務(wù)) GOTO 跳到匹配的規則(通過(guò)LABEL來(lái)標識),有點(diǎn)類(lèi)似程序語(yǔ)言中的GOTO IMPORT{ type} 導入一個(gè)文件或者一個(gè)程序執行后而生成的規則集到當前文件 WAIT_FOR_SYSFS 等待一個(gè)特定的設備文件的創(chuàng )建。主要是用作時(shí)序和依賴(lài)問(wèn)題。 PTIONS 特定的選項: last_rule 對這類(lèi)設備終端規則執行; ignore_device 忽略當前規則; ignore_remove 忽略接下來(lái)的并移走請求。 all_partitions 為所有的磁盤(pán)分區創(chuàng )建設備文件。 我們給出一個(gè)列子來(lái)解釋如何使用這些鍵。下面的例子來(lái)自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個(gè)規則,每一個(gè)都是KERNEL或者ACTION鍵開(kāi)頭: *第一個(gè)規則是缺省的,他匹配任意被內核識別到的設備,然后設定這些設備的屬組是root,組是root,訪(fǎng)問(wèn)權限模式是0600(-rw——-)。這也是一個(gè)安全的缺省設置保證所有的設備在默認情況下只有root可以讀寫(xiě)。 *第二個(gè)規則也是比較典型的規則了。它匹配終端設備(tty),然后設置新的權限為0600,所在的組是tty。它也設置了一個(gè)特別的設備文件名:%K。在這里例子里,%k代表設備的內核名字。那也就意味著(zhù)內核識別出這些設備是什么名字,就創(chuàng )建什么樣的設備文件名。 *第三行開(kāi)始的KERNEL==”scd[0-9]*”,表示 SCSI CD-ROM 驅動(dòng). 它創(chuàng )建一對設備符號連接:cdrom和cdrom-%k。 *第四行,開(kāi)始的 KERNEL==”hd[a-z]“, 表示ATA CDROM驅動(dòng)器。這個(gè)規則創(chuàng )建和上面的規則相同的符號連接。ATA CDROM驅動(dòng)器需要sysfs值以來(lái)區別別的ATA設備,因為SCSI CDROM可以被內核唯一識別。. *第五行以 ACTION==”add”開(kāi)始,它告訴udev增加 /sbin/modprobe sg 到命令列表,當任意SCSI設備增加到系統后,這些命令將執行。其效果就是計算機應該會(huì )增加sg內核模塊來(lái)偵測新的SCSI設備。 當然,上面僅僅是一小部分例子,如果你的系統采用了udev方式,那你應該可以看到更多的規則。如果你想修改設備的權限或者創(chuàng )建信的符號連接,那么你需要熟讀這些規則,特別是要仔細注意你修改的那些與之相關(guān)的設備。 修改你的udev配置 在修改udev配置之前,我們一定要仔細,通常的考慮是:你最好不要修改系統預置的那些規則,特別不要指定影響非常廣泛的配置,比如上面例子中的第一行。不正確的配置可能會(huì )導致嚴重的系統問(wèn)題或者系統根本就無(wú)法這個(gè)正確的訪(fǎng)問(wèn)設備。 而我們正確的做法應該是在/etc/udev/rules.d/下創(chuàng )建一個(gè)信的規則文件。確定你給出的文件的后綴是rules文件名給出的數字序列應該比標準配置文件高。比如,你可以創(chuàng )建一個(gè)名為99-my-udev.rules的規則文件。在你的規則文件中,你可以指定任何你想修改的配置,比如,假設你修改修改floppy設備的所在組,還準備創(chuàng )建一個(gè)信的符號連接/dev/floppy,那你可以這么寫(xiě): KERNEL==”fd[0-9]*”, GROUP=”users”, SYMLINK+=”floppy” 有些發(fā)行版本,比如Fedora,采用了外部腳本來(lái)修改某些特定設備的屬組,組關(guān)系和權限。因此上面的改動(dòng)可能并不見(jiàn)得生效。如果你遇到了這個(gè)問(wèn)題,你就需要跟蹤和修改這個(gè)腳本來(lái)達到你的目的;蛘吣憧梢孕薷腜ROGRAM或RUN鍵的值來(lái)做到這點(diǎn)。 某些規則的修改可能需要更深的挖掘。比如,你可能想在一個(gè)設備上使用sysfs信息來(lái)唯一標識一個(gè)設備。這些信息最好通過(guò)udevinfo命令來(lái)獲取。 $ udevinfo –a –p $(udevinfo –q path –n /dev/hda) 上面的命令兩次使用udevinfo:一次是返回sysfs設備路徑(他通常和我們看到的Linux設備文件名所在路徑--/dev/hda--不同);第二次才是查詢(xún)這個(gè)設備路徑,結果將是非常常的syfs信息匯總。你可以找到最夠的信息來(lái)唯一標志你的設備,你可以采用適當的替換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==”P(pán)IIX_IDE” ATTRS{broken_parity_status}==”0″ ATTRS{enable}==”1″ ATTRS{modalias}==”pci:v00008086d000024CAsv0000144Dsd0000C009bc01sc01i8a” ATTRS{local_cpus}==”1″ ATTRS{irq}==”11″ ATTRS{class}==”0×01018a” ATTRS{subsystem_device}==”0xc009″ ATTRS{subsystem_vendor}==”0×144d” ATTRS{device}==”0×24ca” ATTRS{vendor}==”0×8086″ looking at parent device '/devices/pci0000:00': KERNELS==”pci0000:00″ SUBSYSTEMS==”" DRIVERS==”" 舉一個(gè)例子:假設你想修改USB掃描儀的配置。通過(guò)一系列的嘗試,你已經(jīng)為這個(gè)掃描儀標識了Linux設備文件(每次打開(kāi)掃描儀時(shí),名字都會(huì )變)。你可以使用上面的命令替換這個(gè)正確的Linux設備文件名,然后定位輸出的采用SYSFS{idVendor}行和SYSFS{idProduct}行。最后你可以使用這些信息來(lái)為這個(gè)掃描儀創(chuàng )建新的選項。 SYSFS{idVendor}==”0686″, \ SYSFS{idProduct}==”400e”, \ SYMLINK+=”scanner”, MODE=”0664″, \ group=”scanner” 上面的例子表示將掃描儀的組設置為scanner,訪(fǎng)問(wèn)權限設置為0664,同時(shí)創(chuàng )建一個(gè)/dev/scanner的符號連接。 |