在 sysfs 下的很多 kobject 下都有 uevent 屬性,它主要用於核心與 udev (自動裝置發現程式)之間的一個通訊介面;從 udev 本身與核心的通訊介面 netlink 協議通訊端來說,它並不需要知道裝置的 uevent 屬性檔案,但多了 uevent 這樣一個介面,可用於 udevmonitor 通過核心向 udevd (udev 背景程式)發送訊息,也可用於檢查裝置本身所支援的 netlink 訊息上的環境變數,這個特性一般用於開發人員調試 udev 規則檔案, udevtrigger 這個調試工具本身就是以寫各裝置的 uevent 屬性檔案實現的。 這些 uevent 屬性檔案一般都是可寫的,其中 /sys/devices/ 樹下的很多 uevent 屬性在較新核心下還支援可讀:
# find /sys/ -type f -name uevent -ls 11 0 -rw-r--r-- 1 root root 4096 12月 12 21:10 /sys/devices/platform/uevent 1471 0 -rw-r--r-- 1 root root 4096 12月 12 21:10 /sys/devices/platform/pcspkr/uevent 3075 0 -rw-r--r-- 1 root root 4096 12月 12 21:10 /sys/devices/platform/vesafb.0/uevent 3915 0 -rw-r--r-- 1 root root 4096 12月 12 21:10 /sys/devices/platform/serial8250/uevent 3941 0 -rw-r--r-- 1 root root 4096 12月 12 21:10 /sys/devices/platform/serial8250/tty/ttyS2/uevent 3950 0 -rw-r--r-- 1 root root 4096 12月 12 21:10 /sys/devices/platform/serial8250/tty/ttyS3/uevent 5204 0 -rw-r--r-- 1 root root 4096 12月 12 21:10 /sys/devices/platform/i8042/uevent [...] 912 0 -rw-r--r-- 1 root root 4096 12月 12 21:17 /sys/devices/pci0000:00/0000:00:02.5/uevent [...]
|
上面截取的最後一個是 SCSI 硬碟控制器裝置的 uevent 屬性檔案,這些 /devices/ 屬性檔案都支援寫入,當前支援寫入的參數有 "add","remove","change","move","online","offline"。如,寫入 "add",這樣可以向 udevd 發送一條 netlink 訊息,讓它再重新一遍相關的 udev 規則檔案;這個功能對開發人員調試 udev 規則檔案很有用。
# echo add > /sys/devices/pci0000:00/0000:00:02.5/uevent
|
使用驅動(PCI)的 sysfs 屬性檔案, bind, unbind 和 new_id 在裝置驅動 /sys/bus/*/driver/... 下可以看到很多驅動都有 bind, unbind, new_id 這三個屬性,
# find /sys/bus/*/drivers/ -name bind -ls... |
每一個裝置驅動程式在程式內以某種方式註明了可用於哪些硬體,如所有的 PCI 驅動都使用 MODULE_DEVICE_TABLE 聲明了所能驅動的 PCI 硬體的 PCI 裝置號。但驅動程式不能預知未來,未來生產的新的硬體有可能相容現有硬體的工作方式,就還可以使用現有硬體驅動程式來工作。在 bind 和 unbind 發明以前,這種情況除了修改 PCI 裝置驅動程式的 DEVICE_TABLE 段落,重新編譯驅動程式,以外別無他法,在 2.6 核心上添加了 bind 和 unbind 之後可以在不重新編譯的情況下對裝置和驅動之間進行手工方式地綁定。 而且對於有些硬體裝置可以有多份驅動可用,但任何具體時刻只能有一個驅動程式來驅動這個硬體,這時可以使用 bind/unbind 來強制使用和不使用哪一個驅動程式;(注意關於多種驅動程式的選擇,更好的管理方法是使用 modprobe.conf 設定檔,需要重啟才生效,而 bind/unbind 提供的是一種臨時的無需重啟立即生效的途徑;) 使用它們可以強制綁定某個裝置使用或強制不使用某個驅動程式,操作方法就是通過 bind 和 unbind 介面。
#find /sys/-type f ( -name bind -or -name unbind -or -name new_id ) -ls 69 0 -rw-r--r-- 1 root root 4096 12月 12 22:12 /sys/devices/virtual/vtconsole/vtcon0/bind 3072 0 --w------- 1 root root 4096 12月 12 22:15 /sys/bus/platform/drivers/vesafb/unbind[...] 6489 0 --w------- 1 root root 4096 12月 12 22:09 /sys/bus/pci/drivers/8139too/unbind 6490 0 --w------- 1 root root 4096 12月 12 22:09 /sys/bus/pci/drivers/8139too/bind 6491 0 --w------- 1 root root 4096 12月 12 22:15 /sys/bus/pci/drivers/8139too/new_id |
這個結果中特別提到了 8139too 這份驅動程式的這三個屬性檔案,
# find /sys/bus/pci/drivers/8139too/ -ls 6435 0 drwxr-xr-x 2 root root 0 12月 12 22:08 /sys/bus/pci/drivers/8139too/ 6436 0 lrwxrwxrwx 1 root root 0 12月 12 22:08 /sys/bus/pci/drivers/8139too/0000:00:0e.0 -> ../../../../devices/pci0000:00/0000:00:0e.0 6485 0 lrwxrwxrwx 1 root root 0 12月 12 22:08 /sys/bus/pci/drivers/8139too/module -> ../../../../module/8139too 6488 0 --w------- 1 root root 4096 12月 12 22:08 /sys/bus/pci/drivers/8139too/uevent 6489 0 --w------- 1 root root 4096 12月 12 22:08 /sys/bus/pci/drivers/8139too/unbind 6490 0 --w------- 1 root root 4096 12月 12 22:08 /sys/bus/pci/drivers/8139too/bind 6491 0 --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 addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state 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 eth03: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN 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 addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN 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 addr1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo3: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop state DOWN link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff4: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000 link/ether 00:14:2a:d1:16:72 brd ff:ff:ff:ff:ff:ff |
這一段操作過程示範了如何對 PCI 裝置 "0000:00:0e.0" 強製取消綁定 "8139too" 驅動和強制綁定 "8139too" 驅動: 對 unbind 屬性寫入匯流排號碼(bus_id)即是強製取消綁定; 對 bind 屬性寫入匯流排號碼(bus_id)即是強制綁定; 注意,它要求的寫入的是匯流排號碼,對應於PCI裝置的匯流排號碼是按照 "domain(4位):bus(2位):slot(2位):function號(不限)" 的方式組織,是可以從其裝置 kobject 節點上找到,而其它類型的匯流排有各自不同的規則; 請特別注意: 在這一個例子中, "echo 0000:00:0e.0 > /sys/bus/pci/drivers/8139too/unbind" 這第一個寫入命令以 "No such device" 為錯誤退出,而後續的 "echo -n" 命令則可以成功。這是因為核心在對匯流排號碼進行匹配時過於嚴格了,通常的 "echo" 命令寫入一個字串會以一個分行符號結束輸出,核心所接收到的是帶有這個分行符號的 bus_id 字串,將它與核心資料結構中的真正的 bus_id 字串相比較,當然不能找到;所幸的是,這個問題在最新的 2.6.28 開發中的核心上已已經解決,它將這個比較函數改為一個特殊實現的字串比較,自動忽略結尾處的分行符號,在 2.6.28-rc6 核心上測試,不帶"-n"參數的 echo 命令已經可以寫入成功。 而 new_id 屬性檔案也可以以另一種途徑解決新的裝置號問題:它是一個唯寫的驅動屬性,可用於向其中寫新的裝置號。它支援寫入 2至7個十六進位整形參數,分別代表 vendor, device, subvendor, subdevice, class, class_mask, driver_data 最少為 2個是因為一個 PCI裝置主要以廠商號(vendor)和裝置號(device)所唯一標定,其它 5個參數如果不輸入則預設值為 PCI_ANY_ID(0xffff)。
5441 0 --w------- 1 root root 4096 12月 14 18:15 /sys/bus/pci/drivers/8139too/new_id |
從 8139too 驅動上可以看到它當前所靜態支援的裝置號碼列表,其中包括當前系統中的裝置 10ec:8139, 假設未來有一款 8140 裝置也滿足 8139 裝置的硬體通訊協議,於是可以使用 8139too 驅動程式來驅動它,操作如下
# echo '10ec 8140' > /sys/bus/pci/drivers/8139too/new_id |
這在不更新驅動程式的情況下調試裝置很有用處。 |