深入講述Linux uevent屬性文件系統(tǒng)
在向大家詳細介紹Linux uevent屬性文件之前,首先讓大家了解下Linux系統(tǒng),然后全面介紹Linux uevent屬性文件,希望對大家有用。在 sysfs 下的很多 kobject 下都有 Linux uevent屬性,它主要用于內(nèi)核與 udev (自動設備發(fā)現(xiàn)程序)之間的一個通信接口;從 udev 本身與內(nèi)核的通信接口 netlink 協(xié)議套接字來說,它并不需要知道設備的 Linux uevent屬性文件,但多了 uevent 這樣一個接口。
可用于 udevmonitor 通過內(nèi)核向 udevd (udev 后臺程序)發(fā)送消息,也可用于檢查設備本身所支持的 netlink 消息上的環(huán)境變量,這個特性一般用于開發(fā)人員調(diào)試 udev 規(guī)則文件, udevtrigger 這個調(diào)試工具本身就是以寫各設備的 Linux uevent屬性文件實現(xiàn)的。
這些 Linux uevent屬性文件一般都是可寫的,其中 /sys/devices/ 樹下的很多 Linux uevent屬性在較新內(nèi)核下還支持可讀:
# find /sys/ -type f -name uevent -ls
110 -rw-r--r-- 1 root root 4096 12月 12 21:10 \
/sys/devices/platform/uevent
14710 -rw-r--r-- 1 root root 4096 12月 12 21:10 \
/sys/devices/platform/pcspkr/uevent
30750 -rw-r--r-- 1 root root 4096 12月 12 21:10 \
/sys/devices/platform/vesafb.0/uevent
39150 -rw-r--r-- 1 root root 4096 12月 12 21:10 \
/sys/devices/platform/serial8250/uevent
39410 -rw-r--r-- 1 root root 4096 12月 12 21:10 \
/sys/devices/platform/serial8250/tty/ttyS2/uevent
39500 -rw-r--r-- 1 root root 4096 12月 12 21:10 \
/sys/devices/platform/serial8250/tty/ttyS3/uevent
52040 -rw-r--r-- 1 root root 4096 12月 12 21:10 \
/sys/devices/platform/i8042/uevent
[...]
9120 -rw-r--r-- 1 root root 4096 12月 12 21:17 \
/sys/devices/pci0000:00/0000:00:02.5/uevent
[...]
上面截取的最后一個是 SCSI 硬盤控制器設備的 Linux uevent屬性文件,這些 /devices/ 屬性文件都支持寫入,當前支持寫入的參數(shù)有 "add","remove","change","move","online","offline"。如,寫入 "add",這樣可以向 udevd 發(fā)送一條 netlink 消息,讓它再重新一遍相關的 udev 規(guī)則文件;這個功能對開發(fā)人員調(diào)試 udev 規(guī)則文件很有用。
# echo add > /sys/devices/pci0000:00/0000:00:02.5/uevent使用驅(qū)動(PCI)的 sysfs 屬性文件, bind, unbind 和 new_id在設備驅(qū)動 /sys/bus/*/driver/... 下可以看到很多驅(qū)動都有 bind, unbind, new_id 這三個屬性,
# find /sys/bus/*/drivers/ -name bind -ls
...
每一個設備驅(qū)動程序在程序內(nèi)以某種方式注明了可用于哪些硬件,如所有的 PCI 驅(qū)動都使用 MODULE_DEVICE_TABLE 聲明了所能驅(qū)動的 PCI 硬件的 PCI 設備號。但驅(qū)動程序不能預知未來,未來生產(chǎn)的新的硬件有可能兼容現(xiàn)有硬件的工作方式,就還可以使用現(xiàn)有硬件驅(qū)動程序來工作。在 bind 和 unbind 發(fā)明以前,這種情況除了修改 PCI 設備驅(qū)動程序的 DEVICE_TABLE 段落,重新編譯驅(qū)動程序,以外別無他法,在 2.6 內(nèi)核上添加了 bind 和 unbind 之后可以在不重新編譯的情況下對設備和驅(qū)動之間進行手工方式地綁定。
而且對于有些硬件設備可以有多份驅(qū)動可用,但任何具體時刻只能有一個驅(qū)動程序來驅(qū)動這個硬件,這時可以使用 bind/unbind 來強制使用和不使用哪一個驅(qū)動程序;(注意關于多種驅(qū)動程序的選擇,更好的管理方法是使用 modprobe.conf 配置文件,需要重啟才生效,而 bind/unbind 提供的是一種臨時的無需重啟立即生效的途徑;)
使用它們可以強制綁定某個設備使用或強制不使用某個驅(qū)動程序,操作方法就是通過 bind 和 unbind 接口。
# find /sys/ -type f \( -name bind -or -name unbind -or -name new_id \) -ls
690 -rw-r--r-- 1 root root 4096 12月 12 22:12 \
/sys/devices/virtual/vtconsole/vtcon0/bind
30720 --w------- 1 root root 4096 12月 12 22:15 \
/sys/bus/platform/drivers/vesafb/unbind
[...]
64890 --w------- 1 root root 4096 12月 12 22:09 \
/sys/bus/pci/drivers/8139too/unbind
64900 --w------- 1 root root 4096 12月 12 22:09 \
/sys/bus/pci/drivers/8139too/bind
64910 --w------- 1 root root 4096 12月 12 22:15 \
/sys/bus/pci/drivers/8139too/new_id
這個結果中特別提到了 8139too 這份驅(qū)動程序的這三個屬性文件,
# find /sys/bus/pci/drivers/8139too/ -ls
64350 drwxr-xr-x 2 root root0 12月 12 22:08 \
/sys/bus/pci/drivers/8139too/
64360 lrwxrwxrwx 1 root root0 12月 12 22:08 \
/sys/bus/pci/drivers/8139too/0000:00:0e.0 -> ../../../../devices/pci0000:00/0000:00:0e.0
64850 lrwxrwxrwx 1 root root0 12月 12 22:08 \
/sys/bus/pci/drivers/8139too/module -> ../../../../module/8139too
64880 --w------- 1 root root 4096 12月 12 22:08 \
/sys/bus/pci/drivers/8139too/uevent
64890 --w------- 1 root root 4096 12月 12 22:08 \
/sys/bus/pci/drivers/8139too/unbind
64900 --w------- 1 root root 4096 12月 12 22:08 \
/sys/bus/pci/drivers/8139too/bind
64910 --w------- 1 root root 4096 12月 12 22:08 \
/sys/bus/pci/drivers/8139too/new_id
# echo 0000:00:0e.0 > /sys/bus/pci/drivers/8139too/unbind
-bash: echo: write error: 沒有那個設備
# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
2: eth0:
UNKNOWN qlen 1000
link/ether 00:14:2a:d1:16:72 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.102/24 brd 192.168.1.255 scope global eth0
3: bond0:
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
# echo -n 0000:00:0e.0 > /sys/bus/pci/drivers/8139too/unbind
# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
3: bond0:
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
# echo -n 0000:00:0e.0 > /sys/bus/pci/drivers/8139too/bind
# ip addr
1: lo:
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
3: bond0:
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
4: eth0:
link/ether 00:14:2a:d1:16:72 brd ff:ff:ff:ff:ff:ff
這一段操作過程演示了如何對 PCI 設備 "0000:00:0e.0" 強制取消綁定 "8139too" 驅(qū)動和強制綁定 "8139too" 驅(qū)動:
對 Linux uevent屬性寫入總線號碼(bus_id)即是強制取消綁定;
對 bind 屬性寫入總線號碼(bus_id)即是強制綁定;
注意,它要求的寫入的是總線號碼,對應于PCI設備的總線號碼是按照 "domain(4位):bus(2位):slot(2位):function號(不限)" 的方式組織,是可以從其設備 kobject 節(jié)點上找到,而其它類型的總線有各自不同的規(guī)則;
請?zhí)貏e注意: 在這一個例子中, "echo 0000:00:0e.0 > /sys/bus/pci/drivers/8139too/unbind" 這第一個寫入命令以 "No such device" 為錯誤退出,而后續(xù)的 "echo -n" 命令則可以成功。這是因為內(nèi)核在對總線號碼進行匹配時過于嚴格了,通常的 "echo" 命令寫入一個字符串會以一個換行符結束輸出,內(nèi)核所接收到的是帶有這個換行符的 bus_id 字符串,將它與內(nèi)核數(shù)據(jù)結構中的真正的 bus_id 字符串相比較,當然不能找到;所幸的是,這個問題在最新的 2.6.28 開發(fā)中的內(nèi)核上已已經(jīng)解決,它將這個比較函數(shù)改為一個特殊實現(xiàn)的字符串比較,自動忽略結尾處的換行符,在 2.6.28-rc6 內(nèi)核上測試,不帶"-n"參數(shù)的 echo 命令已經(jīng)可以寫入成功。
而 new_id 屬性文件也可以以另一種途徑解決新的設備號問題:它是一個只寫的驅(qū)動屬性,可用于向其中寫新的設備號。它支持寫入 2至7個十六進制整形參數(shù),分別代表 vendor, device, subvendor, subdevice, class, class_mask, driver_data 最少為 2個是因為一個 PCI設備主要以廠商號(vendor)和設備號(device)所唯一標定,其它 5個參數(shù)如果不輸入則缺省值為 PCI_ANY_ID(0xffff)。
54410 --w------- 1 root root 4096 12月 14 18:15 \
/sys/bus/pci/drivers/8139too/new_id
從 8139too 驅(qū)動上可以看到它當前所靜態(tài)支持的設備號碼列表,其中包括當前系統(tǒng)中的設備 10ec:8139, 假設未來有一款 8140 設備也滿足 8139 設備的硬件通訊協(xié)議,于是可以使用 8139too 驅(qū)動程序來驅(qū)動它,操作如下# echo '10ec8140'>/sys/bus/pci/drivers/8139too/new_id這在不更新驅(qū)動程序的情況下調(diào)試設備很有用處。以上介紹Linux uevent屬性文件。
【編輯推薦】