11.6 透過 udev 規則影響核心設備事件處理

udev 規則可以比對核心新增至事件本身的任何內容,或者任何由核心輸出到 sysfs 的資訊。規則也可向外部程式要求其他資訊。每個事件都會與所有指定規則進行比對。所有規則都位於 /etc/udev/rules.d 目錄中。

規則檔案中的每一行都包含至少一個金鑰值組合。金鑰類型共有兩種,包括比對和指定金鑰。當所有比對金鑰都與指定值相符時就會套用規則,而該指定值就會指定給指定金鑰。相符的規則可以指定設備節點名稱、新增指向該節點的符號連結,或是執行指定程式成為事件處理的一部份。如果找不到任何符合規則,就會使用預設的設備節點名稱來建立設備節點。如需有關規則語法和為比對或輸入資料所提供之金鑰的詳細資訊,請參閱 udev 線上文件。以下範例規則提供了對 udev 規則語法的基本介紹。所有範例規則均來自 /etc/udev/rules.d/50-udev-default.rules 之下的 udev 預設規則集。

範例 11-1 範例 udev 規則

# console
KERNEL=="console", MODE="0600", OPTIONS="last_rule"

# serial devices
KERNEL=="ttyUSB*", ATTRS{product}=="[Pp]alm*Handheld*", SYMLINK+="pilot"

# printer
SUBSYSTEM=="usb", KERNEL=="lp*", NAME="usb/%k", SYMLINK+="usb%k", GROUP="lp"

# kernel firmware loader
SUBSYSTEM=="firmware", ACTION=="add", RUN+="firmware.sh"

主控台規則包含三個金鑰︰一個比對金鑰 (KERNEL) 與兩個指派金鑰 (MODEOPTIONS)。KERNEL 比對規則用於搜尋類型為主控台的所有項目的設備清單。只有完全符合的項目才有效,才會觸發此規則讓其執行。MODE 金鑰用於將特殊權限指派給設備節點,在此案例中,僅此設備的擁有者才會被指派讀取與寫入權限。OPTIONS 金鑰用於將此規則做為要套用至所有此類型設備的最後一條規則。符合此特殊設備類型的任何後續規則都不會生效。

序列設備規則在 50-udev-default.rules 中雖已不再可用,但仍值得瞭解一下。它包含兩個比對金鑰 (KERNELATTRS) 與一個指派金鑰 (SYMLINK)。KERNEL 金鑰用於搜尋類型為 ttyUSB 的所有設備。使用 * 萬用字元時,此金鑰可比對多部此類設備。第二個比對金鑰 ATTRS 用於檢查 sysfs 中針對 ttyUSB 設備的 product 屬性檔案是否包含特定字串。指派金鑰 (SYMLINK) 用於觸發將符號連結新增至 /dev/pilot 下的此設備。此金鑰中使用的運算子 (+=) 將告知 udev 額外執行此動作,即使先前或之後的規則會新增其他符號連結也是如此。由於此規則包含兩個比對金鑰,因此僅當兩個條件均滿足時才適用。

印表機規則可處理 USB 印表機,它包含兩個比對金鑰,必須同時套用這兩個金鑰才能套用整個規則 (SUBSYSTEMKERNEL)。三個指派金鑰用於命名此設備類型 (NAME)、建立符號設備連結 (SYMLINK) 以及分組此設備類型的成員 (GROUP)。在 KERNEL 金鑰中使用 * 萬用字元可使其符合多部 lp 印表機設備。可以在 NAMESYMLINK 金鑰中使用替代項,透過內部設備名稱延伸這些字串。例如,第一部 lp USB 印表機的符號連結會讀取 /dev/usblp0

核心韌體載入程式規則可讓 udev 在執行時期透過外部輔助程式程序檔載入其他韌體。SUBSYSTEM 比對金鑰可搜尋韌體子系統。ACTION 金鑰可檢查是否已新增任何屬於韌體子系統的設備。RUN+= 金鑰可觸發執行 firmware.sh 程序檔以查找要載入的韌體。

某些一般特性適用於所有規則︰

11.6.1 在 udev 規則中使用運算子

建立金鑰時,您可以根據要建立的金鑰類型從多個不同的運算子中進行選擇。比對金鑰通常僅用於尋找符合或明顯不符合搜尋值的值。比對金鑰可包含以下運算子︰

==

比較是否相等。如果金鑰包含搜尋模式,則所有符合此模式的結果均有效。

!=

比較是否不相等。如果金鑰包含搜尋模式,則所有符合此模式的結果均有效。

指派金鑰可使用以下運算子︰

=

將某個值指派給金鑰。如果金鑰先前包含值清單,則此金鑰將重設並僅指派單一值。

+=

將某個值新增至包含項目清單的金鑰。

:=

指派最終值。不允許後續規則再做任何變更。

11.6.2 在 udev 規則中使用替代項

udev 規則支援使用佔位符與替代項。使用方式與任何其他程序檔中的方式類似。udev 規則可使用以下替代項︰

%r, $root

依預設為設備目錄 /dev

%p, $devpath

DEVPATH 的值。

%k, $kernel

KERNEL 的值或內部設備名稱。

%n, $number

設備編號。

%N, $tempnode

設備檔案的暫存名稱。

%M, $major

設備的主要編號。

%m, $minor

設備的次要編號。

%s{attribute}, $attr{屬性}

sysfs 屬性的值 (由屬性指定)。

%E{變數}, $attr{變數}

環境變數的值 (由變數指定)。

%c, $result

PROGRAM 的輸出。

%%

% 字元。

$$

$ 字元。

11.6.3 使用 udev 比對金鑰

比對金鑰描述在可以套用 udev 規則之前必須滿足的條件。以下為可用的比對金鑰:

ACTION

事件動作的名稱,例如新增或移除設備時的 addremove

DEVPATH

事件設備的設備路徑,例如 DEVPATH=/bus/pci/drivers/ipw3945,用於搜尋與 ipw3945 驅動程式相關的所有事件。

KERNEL

事件設備的內部 (核心) 名稱。

SUBSYSTEM

事件設備的子系統,例如 SUBSYSTEM=usb,適用於與 USB 設備相關的所有事件。

ATTR{檔案名稱}

事件設備的 sysfs 屬性。例如,若要比對 vendor 屬性檔案名稱中包含的字串,可以使用 ATTR{vendor}=="On[sS]tream"

KERNELS

可讓 udev 向上搜尋符合設備名稱的設備路徑。

SUBSYSTEMS

可讓 udev 向上搜尋符合設備子系統名稱的設備路徑。

DRIVERS

可讓 udev 向上搜尋符合設備驅動程式名稱的設備路徑。

ATTRS{檔案名稱}

可讓 udev 向上搜尋符合 sysfs 屬性值的設備路徑。

ENV{金鑰}

環境變數的值,例如 ENV{ID_BUS}="ieee1394,用於搜尋與 FireWire 匯流排 ID 相關的所有事件。

PROGRAM

可讓 udev 執行外部程式。若要成功執行,程式必須以離開碼零返回。RESULT 金鑰可使用程式的輸出 (列印至 stdout)。

RESULT

比對上次 PROGRAM 呼叫的輸出字串。即可將此金鑰包含於相同規則中 (如 PROGRAM 金鑰),也可含於後續規則中。

11.6.4 使用 udev 指派金鑰

與上述比對金鑰不同,指派金鑰不會說明必須滿足的條件,而是將值、名稱和動作指派給透過 udev 維護的設備節點。

NAME

要建立之設備節點的名稱。如果規則已設定了節點名稱,則將忽略適用於此節點的所有其他含 NAME 金鑰的規則。

SYMLINK

與要建立的節點相關聯之符號連結的名稱。可以為多項比對規則新增符號連結以便使用設備節點進行建立。您還可以使用空格字元分隔符號連結名稱,從而為一項規則中的一個節點指定多個符號連結。

OWNER, GROUP, MODE

新設備節點的權限。在此處指定的值將覆寫已編譯的任何項目。

ATTR{金鑰}

指定要寫入事件設備之 sysfs 屬性中的值。如果使用運算子 ==,也會使用此金鑰來比對 sysfs 屬性的值。

ENV{金鑰}

告知 udev 將某變數輸出到環境。如果使用運算子 ==,也會使用此金鑰來比對環境變數。

RUN

告知 udev 將某程式新增至要為此設備執行的程式清單。對極短任務套用此項時要格外小心,避免封鎖此設備的其他事件。

LABEL

GOTO 可以跳轉之處新增一個標籤。

GOTO

通知 udev 跳過多項規則並繼續使用含有由 GOTO 金鑰所參考之標籤的規則。

IMPORT{類型}

將變數載入事件環境,如外部程式的輸出。udev 可輸入多種不同類型的變數。如果未指定任何類型,udev 會根據檔案權限的可執行位元嘗試自行決定類型。

  • program 可告知 udev 執行外部程式並輸入其輸出。

  • file 可告知 udev 輸入文字檔。

  • parent 可告知 udev 輸入父代設備中儲存的金鑰。

WAIT_FOR_SYSFS

告知 udev 等待要為特定設備建立的指定 sysfs 檔案,例如,WAIT_FOR_SYSFS="ioerr_cnt" 將通知 udev 在 ioerr_cnt 檔案建立完成前需一直等待。

OPTIONS

OPTION 金鑰可以包含多個值︰

  • last_rule 告知 udev 忽略所有後續規則。

  • ignore_device 告知 udev 完全忽略此事件。

  • ignore_remove 告知 udev 忽略針對該設備的所有後續移除事件。

  • all_partitions 告知 udev 為區塊設備上的所有可用分割區建立設備節點。