2008/08/19

Hal Dbus udev automount usb device?

一直以來,總有人要問我 automount device, 也就是自動掛載裝置,通常指的是 USB devices. 事實上有套件 autofs, usbmount, 不過這邊來說說更一般化的東西。這篇文章主要來自udev, hal, 與 dbus(註:2010/05/14, 此篇已經不見了,請見我的新文章)。例如要做 automount, 有三個東西要瞭解一下才行:
- udev: 早期,最麻煩的是建 /dev 下的 node, 這個現在由 udev 解決
- hal: 要做 automount 另一個麻煩,就是不知道裝置的清單與資訊,現在由 hal 解決。 hal 並不是要去讓你怎樣跟硬體溝通,不是用來 config/setup hardware 或是 use hardware
- d-bus: 第三,就是以前需要與硬體溝通的技巧上,很難用 Interrupt, 也很難寫個 daemon 去叫適當的程式來處理 Hardware 的訊息,例如 automount 這件事,裝置插進去,不知道要叫誰來 mount,mount 的參數不知道該是什麼,不同的 filesystem 搞不好還有不同的動作,譬如要加 -t ntfs 什麼的, 現在由 d-bus 解決

在 usb storage 的 source code (include/scsi/sd.h or drivers/scsi/sd.c)中,有定義這個常數:
裝置可以有 #define SD_MAX_DISKS (((26 * 26) + 26 + 1) * 26) 這麼多個,其實正是 a-z, aa-zz, aaa-zzz 個。至於一般記憶卡的,因為有兩個動作,一個是接上讀卡機,一個是接上記憶卡,因此可以這麼理解:

1. 對讀卡機而言,能插的槽是固定的,一插上去,就 export 槽數,那就像硬碟一樣, 所以不同的插槽是分配 /dev/sd[a-z]*
2. 當你插記憶卡上去的時候,讀卡機的狀態就改變了,它重新 export, 就像剛做完 fdisk 一樣的機制,此時,kernel 會讀到記憶卡的分區,就配給 partition /dev/sd[a-z]*[0-9]


參考資料:



Udev 是什麼?
早期的核心採用的是 devfs, 後來以 udev 取代,幫你自動產生 /dev/ 下的節點。

Hall 是什麼?
HAL 並非針對如何使用硬體而設計的,也不是設計來讓你設定硬體組態的,事實上,HAL 是用在應用程式中,讓你取得硬體清單及其硬體組態。所以你會看到 libhal 就是讓你做這樣的事的。當然 hald 就是與 kernel 溝通用來收集資訊的。


D-Bus 是什麼?
簡言之,它是由幾件事組成的,怕翻錯,自己翻譯:1) a wire protocol for exposing a typical object-oriented language/framework to other applications; and 2) a bus daemon that allows applications to find and monitor one another. 以比較通俗的話來說 D-Bus 是 1) 像一個 IPC 系統,可以讓裝置與應用程式溝通,2) 由兩個 bus daemons 提供某種高階的資料結構(lifecycle tracking, service activation, security policy)。

HAL & D-BUS
D-BUS provides asynchronous notification such that HAL can notify other peers on the message-bus when devices are added and removed as well as when properties on a device are changing.
所以 D-Bus 提供非同步的通知訊號,使得裝置組態改變時 HAL 可以透過 Message bus 通知到其他應用程式,譬如硬體插入或移除等。

所以若你要做到 automount usb device, 流程圖大約如下:
1. 插入裝置
2. kernel 透過 udev 將攔截到的資訊,傳到 D-Bus 上去
3. 此時 udev 會因為此項通知,自動產生相對應的 /dev/ 下的節點
4. HAL 再經由 D-Bus 的訊息而被知會新裝置,取得相關的資訊,並通知註冊的應用程式
5. 最後,應用程式被知會後,例如 gnome-volume-manager,再將資料從 HAL 層取出,做出相對應的動作。

1 意見:

雷克斯 提到...

How to get USB device add/remove event from udev

In the following directory "/etc/udev/rules.d/", there are rule files for udev so you can add rules into rule files to call your application:

KERNEL=="sd*", ACTION=="add", RUN+="/usr/bin/my_program %k"
KERNEL=="sd*", ACTION=="remove", RUN+="/usr/bin/my_program %k"


1. KERNEL - Match against the kernel name for the device
2. ACTION - A environment variable to detect whether the device is being connected or disconnected. The value will be either "add" or "remove" respectively.


String substitutions

When writing rules which will potentially handle multiple similar devices, udev's printf-like string substitution operators are very useful. You can simply include these operators in any assignments your rule makes, and udev will evaluate them when they are executed.

The most common operators are %k and %n. %k evaluates to the kernel name for the device, e.g. "sda3" for a device that would (by default) appear at /dev/sda3. %n evaluates to the kernel number for the device (the partition number for storage devices), e.g. "3" for /dev/sda3.

String matching

As well as matching strings exactly, udev allows you to use shell-style pattern matching. There are 3 patterns supported:

* - match any character, zero or more times

? - match any character exactly once
[] - match any single character specified in the brackets, ranges are also permitted


P.S.
1. Rule files must have the .rules suffix.
2. Files in /etc/udev/rules.d/ are parsed in lexical order, and in some circumstances, the order in which rules are parsed is important. In general, you want your own rules to be parsed before the defaults, so I suggest you create a file at /etc/udev/rules.d/10-local.rules and write all your rules into this file.
For more information about udev rules, please visit http://reactivated.net/writing_udev_rules.html