淺談hotplug, udev, hal, d-bus

接下來要整合一套設備熱插拔的掛載機制, 一下內容是baigoogledu出來並自己理解的知識點, 不妥之處望各位提出.
 
App
 ↑              App等候設備處理信息並掛載設備
D-Bus
 ↑              過濾處理內容後送給D-Bus
HAL             它是一個位於操作系統和驅動程序之上,運行在用戶空間中的服務程序
 ↑              把硬件相關內容送到HAL
udev
 ↑              kernel2.6發現設備變化反映到sysfs, 並通過hotplug機制通知udev
Linux Kernel2.6 自動調用驅動模塊
 
1. 自動掛載磁盤分區的操作從底層來說,是要內核支持的,2.6 內核的sysfs 虛擬文件系統就提供了這一支持,這個文件系統 (/sys/) 通常用於反應系統硬件信息,總線上的設備變化、網絡設備的變化等事件在這裏都能反應出來,這個文件系統的變化配合上內核的 hotplug 機制就可以掌握硬件改動相關的信息.
說到內核的 hotplug 機制,簡單地說就是在硬件發生變化的時候去通知某一用戶態程序,缺省是 /sbin/hotplug,不過現在它已經被 udev 取代了,收到信息之後,udev 會根據 sysfs 的變化調用一些腳本來處理這個事件,這裏的處理是指某個用戶空間的動作,而不是加載驅動,加載驅動是內核自己的事情,在 udev 反應過來之前就完成了.
 
2. 下面輪到我們著名的硬件抽象層(HAL)

HALHardware Abstraction Layer的首字母縮寫。我最早是在Winnt 3.5的幫助中知道這個名詞的,對幫助文檔中的說法我比較認同,所以一直對它抱有好感。不過Windows下的HALLinux下的HAL兩者所指並非相同之物:

Windows下的HAL位於操作系統的最底層,直接操作物理硬件,隔離與硬件相關的信息,爲上層的操作系統和設備驅動程序提供一個統一的接口,起到對硬件的抽象作用。有了HAL,編寫驅動程序就容易多了,因爲HAL的接口不但使用簡單,而且具有更好的可移植性(沒用過)。

Linux 下的HAL:至於對硬件的抽象,Linux內核早就有類似機制,只不過沒有專門的名稱罷了。而LinuxHAL指的並非這個,它不是位於操作系統的最底層,直接操作硬件,相反,它位於操作系統和驅動程序之上,是一個運行在用戶空間中服務程序。

我們知道,Linux和所有的Unix一樣,習慣用文件來抽象設備,任何設備都是一個文件,比如/dev/mouse是鼠標的設備文件。這種方法看起來不錯,每個設備都有統一的形式,但使用並不那麼容易,設備文件名沒有什麼規範,從簡單的一個文件名,你無法得知它是什麼設備,具有有什麼特性。

結果形成這樣的尷尬:有了設備和設備驅動程序,卻不知道如何使用它。這些亂七八糟的設備文件,讓設備的管理和應用程序的開發都變得很麻煩,所以有必要提供一個硬件抽象層,來爲上層應用程序提供一個統一的接口,LinuxHAL就這樣應運而生了。

HAL並不提供諸如拍照和刻錄等之類的功能,相反它只是告訴應用程序,系統中有哪些設備可用,以及這些設備的類型、特性和能力等。主要說來,它提供以下幾項功能:

1.         獲取指定類型的設備列表。

2.         獲取/更改設備的屬性值。

3.         獲取設備具有的能力描述。

4.         設備插入/拔除時,通知相關應用程序。

5.         設備屬性或能力變化時,通知相關應用程序。

udev創建dev下的文件結點,加載驅動程序,讓設備處於可用狀態。而HAL則告訴應用程序,現在有哪些設備可用,這些設備的類型、特性和能力,讓應用程序知道如何使用它們。

設備的屬性管理是HAL最重要任務之一,有的設備屬性來源於實際的硬件,有的來源於設備信息文件(/usr/share/hal/fdi/),有的來源其它配置信息(/usr/share/hwdata/)。設備屬性的都有標準的定義,這些屬性定義是HALSPEC的主要內容之一,可以參考http://people.freedesktop.org/~david/hal-spec/hal-spec.html

 

3.  udev & HAL


1.         實線箭頭爲主動調用,虛線箭頭爲事件上報。
2.         udev通過NetLink註冊內核的設備事件,當有設備插入/拔除時,udev就會收到通知,它會從事件中所帶參數和sysfs中的信息,加載適當的驅動程序,創建dev下的結點,讓設備處於可用的狀態。
3.         udev只是一個框架,它的行爲完全受它的規則所控制,這些規則存放在目錄/etc/udev/rules.d/中,其中90-hal.rules是用來讓udev把設備插入/拔除的事件通過socket socket:/org/freedesktop/hal/udev_event轉發給HAL的。
4.         HAL掛在socket:/org/freedesktop/hal/udev_event上等待事件,有事件發生時就調用函數 hald_udev_data處理,它先從事件中取出主要參數,創建一個hotplug_event對象,把它放入事件隊列中,然後調用 hotplug_event_process_queue處理事件。
5.         函數hotplug_event_begin負責具體事件的處理,它把全部事件分爲四類,並分別處理hotplug_event_begin_sysfs 處理普通設備事件,hotplug_event_begin_acpi處理ACPI事件,hotplug_event_begin_apm處理APM事件,hotplug_event_begin_pmu處理PMU事件。要注意的是,後三者的事件源並非源於udev,而是在device_reprobe 時觸發的 (osspec_device_reprobe/hotplug_reprobe_tree/hotplug_reprobe_generate_add_events/acpi_generate_add_hotplug_event)。
6.         函數hotplug_event_begin_sysfs中,如果是插入設備,則創建一個設備對象,設置設備的屬性,調用相關callouts,然後放入設備列表中,並觸發signal讓dbus通知相關應用程序。如果是拔除設備,則調用相關callouts,然後從設備列表中刪除,並觸發signal讓 dbus通知相關應用程序。
7.         應用程序可以主動調用HAL提供的DBUS接口函數,這些函數在libhal.h中有定義。應用程序也可以註冊HAL的signal,當設備變化時,HAL通過DBUS上報事件給應用程序。
8.         callout是HAL一種擴展方式,它在設備插入/拔除時執行。可以在設備信息文件中(/usr/share/hal目錄)指定。
9.         addon也是HAL一種擴展方式,它與callout的不同之處在於addon往往是事件的觸發者,而不是事件的消費者。HAL的事件源主要源於 udev,而udev源於kernel的hotplug,然而有的設備如電源設備、磁盤設備和特殊按鍵等,它們並不產生hotplug事件。HAL就得不到通知,怎麼辦呢,addon就是用於支持新事件源的擴展方式。比如addon-acpi從/proc/acpi/event或者 /var/run/acpid.socket收到事件,然後轉發成HAL事件。addon-storage檢測光盤或磁盤的狀態,並設置設備的屬性。 addon-keyboard檢測一些特殊按鍵,並觸發相應事件。
access-check/ci-tracker/ck-tracker負責權限的檢查,裏面提到的PolicyKit/ConsoleKit不是太熟悉,有時間再看看。
簡單的說,HAL就是一個設備數據庫,它管理當前系統中所有的設備,你可以以多種靈活的方式去查詢這些設備,可以獲取指定設備的特性,可以註冊設備變化事件。


4. 那 hal 怎麼發出通知呢? 這是利用一個新興的系統內用戶空間消息總線系統 -- dbus 來完成的,hal 會通過 dbus 上的一條消息總線把新加入的塊設備和相關的掛載提示信息,比如加載選項 sync, iocharset 之類的信息發送到總線上來,只等待一個終結者來接受並處理這些信息了.
 
5. 這個終結者對於 gnome 來說就是 gnome-volume-manager (名字太長了,下面簡稱 gvm),它從 dbus 上探聽消息,當發現有設備掛載提示的時候就會嘗試把設備掛載上來。缺省的,還會打開一個 nautilus 瀏覽窗口來瀏覽新掛載上的分區的內容。
嗯,最後一個問題就是怎麼掛了,衆所周知,如果塊設備在 /etc/fstab 裏沒有描述存在的話,掛載就比較麻煩:
  • 本來如果有 fstab 中的 user 屬性的話,普通用戶可以掛載,但  現在沒有,普通用戶沒法掛
  • 如果 sudo 授權的話,用戶可能獲得掛載其他分區的過大權限,危及 系統安全。

pmount 就是這個工具鏈上的最後一環,它可以代表用戶 (運行 gvm 的用戶) 來掛載一個屬於他的可移動存儲設備,即使 fstab 裏沒有這個設備存在,缺省的掛載位置是 /media/ 下,和 塊設備同名,比如 /dev/sda1 掛載到 /media/sda1/ 目錄。
 
嗯,綜上,設備的自動掛載就完成了,呵呵,希望一大堆的關鍵詞沒把大家搞暈,回顧一下: kernel 發現設備變化反應到 sysfs 上並通過 hotplug 機制通知udev, udev 把硬件相關內容送給 hal,hal 過濾、處理之後發送信息到 dbus 上,在 dbus 上等候的 gvm 收到消息後用 pmount 把設備掛上,這樣,設備的自動掛載就完成.

PS:HAL的相關文件:

首先是硬件信息文件fdi的路徑會有:

/usr/share/hal/fdi 通常是由系統程序安裝包提供的文件。

/etc/hal/fdi 這裏是用戶或者管理員修改fdi的位置。

這兩個路徑下各自存在information policy preprobe等3個目錄,用來存放不同用途的fdi文件。後面再解釋。

 

其次是HAL的一些Callout和Addon,他們位於 /usr/lib/hal/scripts 及 /usr/lib/hal/ 下面

 

再有一些與HAL本身相關的配置文件等:

/etc/init.d/hal hal的啓動腳本

/etc/udev/rules.d/95-hal.rules  HAL在UDEV中的規則

/etc/dbus-1/system.d/hal.conf  HAL的一些常用的Interface在DBUS中的權限設置。

 

相關程序

/usr/bin/lshal

/usr/bin/hal-device

/usr/bin/hal-get-property

/usr/bin/hal-set-property

/usr/bin/hal-find-by-capability

/usr/bin/hal-find-by-property

/usr/bin/hal-disable-polling

/usr/bin/hal-is-caller-locked-out

/usr/bin/hal-lock

/usr/sbin

/usr/sbin/hald


本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/colorant/archive/2008/07/04/2611559.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章