Linux-Device-Model-2
Linux Device Model
註1:這篇文章的function prototype都是用kernel version 4.4.0-75(Ubuntu 16.04)(tag v4.4-rc6)。
註2: 裡面的內容,關鍵字和專有名詞我會盡量以英文來呈現。
註3: 這裡面也沒有什麼新花樣,只是我唸書的筆記分享而已。
註4: 目前的檔案只是我暫存用,到時候會post部落格上。

Device Types

在Linux裡,就像在所有的Unix系統,每個裝置(device)都會被分類成底下三種其一:
  • Block devices
  • Character devices
  • Network devices

Block devices』,通常會縮寫成『blkdevs』,這類型的device是屬於可以定位(addressable)的,定位的基準是以device的區塊『block』為單位,並且有可搜尋(seeking)和隨機存取(random access)等特性。Block device可以經由特殊的檔案 - 『block device node』來存取,並且存取前一定要在filesystem裡有掛載(mount)的動作。

Character devices』,通常會縮寫成『cdevs』,這類型的device跟block device剛好相反,通常是不可定址的,只能用串流(stream)的方式來存取資料,單位一般是characters (bytes)。如果要存取這類型的device的話,通常必須經由一個特殊的檔案類型 - 『character device node』。

Ethernet devices』,其實就是我們通稱的network devices,這類型的device會透過實體的適配器(physical adapter)和特殊的協議來存取網路。Network device的話跟其他兩種不一樣,它不能經由device node來存取,必須透過『socker API』這個特殊的介面來存取。但是並不是每個device driver都會有實體的device,有可能會是虛擬的(virtual),用來存取相關的kernel功能,這類型的device通稱為『pseudo devices』。


Device Model

大家應該都知道Linux Kernel是跨架構/平台的一個作業系統核心,所以它必須經得起各種的架構和硬體平台的考驗。舉個例子來說,想要讓一個相同的USB device driver在x86 PC上可以用,那當然也要可以在ARM 平台上運作,即使在這兩種平台上的USB controllers是不同的條件之下,也不能有影響。

到了kernel 2.4,出現了『devfs』,其引入了動態裝置節點(dynamic device node)建立,devfs可以讓kernel介面在 in-memory filesystem中建立device nodes。在devfs這套機制中雖然已經有進步了,但是為其node命名的責任還是落在device driver身上,而且跟kernel的整合並沒有很完美。所以到了『udev』的出現以後,才真正的把device的管理給推到了user space上面去。

Device model』,是一個kernel 2.6開始很重要的結構,提供很準確的device tree來管理與增進power management。為了在kernel裡面實做device-level的power management,就必須要在系統裡面建立一個tree來代表device的拓普(topology)。在早期的kernel版本,所有需要的device node都需要自己在『/dev/』底下去靜態建立,這種舊機制其實還蠻複雜的。而這『Device model』主要的功能如以下三點:
1. Power management.
2. Hotplug.
3. User space communication.

在上面的前提之下,想要將device管理的任務給落到user space上的話,對於其抽象化的概念就非常重要了,因為必須要有一個非常清楚的架構將device driver從controller driver給分離出來,並將硬體的描述從drivers給分離出來,這些事情,主要就是由Kernel的『Device model』所做的,所以要學driver的先決知識很多,其中一個最重要的就是要知道這些分層概念,就像是如果你不懂網路的OSI Layers概念,你就很難將networking code寫的很好一樣。 

在這邊我們可以了解到,這整件事並不是只有一個driver還是user space的程式就可以解決,必須要從上層user space串到下層kernel space,Device driver是Linux kernel 的一部分,負責所有device的偵測,狀態的改變,但是只要將driver給讀進去記憶體後,kernel會作的事只有一個,就是送一個event到user space的daemon - 『udevd』。然後udevd這個user space的device manager就會去接到這些events,在根據相關的組態來決定下一步會發生什麼事。

舉兩個wiki上的例子來幫助理解:

1. 當有一個新的USB 硬碟連接到你的電腦時,kernel會通知udevd,然後udevd在通知udisksd-daemon,最後這個『udisksd-daemon』就會掛載這個file system。
 Kernel --> udev --> udisksd-daemon

2. 當有一個Ethernet cable插進去電腦的Ethernet NIC以後,kernel會通知udevd,然後udevd在通知NetworkManager-daemon。下一步NetworkManager-daemon就會開始為這個NIC啟動『dhclient』分配IP,而後在根據某些組態來設定你的網路,最後一步就是相關的程式就會使用『D-Bus』跟NetworkManager溝通。
 Kernel --> udev --> Network Manager <--> D-Bus <--> Evolution


對於這篇文章,期望會讓你理解整個Device model的概念如下圖:

udev

首先這整個機制,如果沒有碰過kernel space的人,應該很難想像下層kernel space的部份,所以第一個部份先來講一下user space的『udev』。