1. 設備類型linux
linux中主要由3種類型的設備,分別是:數組
設備類型網絡 |
表明設備數據結構 |
特色框架 |
訪問方式模塊化 |
塊設備函數 |
硬盤,光盤ui |
隨機訪問設備中的內容spa |
通常都是把設備掛載爲文件系統後再訪問設計 |
字符設備 |
鍵盤,打印機 |
只能順序訪問(一個一個字符或者一個一個字節) |
通常不掛載,直接和設備交互 |
網絡設備 |
網卡 |
打破了Unix "全部東西都是文件" 的設計原則 |
經過套接字API來訪問 |
除了以上3種典型的設備以外,還有"僞設備",即一些虛擬的設備,僅提供訪問內核功能而已,沒有物理設備與之關聯。
2. 內核模塊
Linux內核是模塊化組成的,內核中的模塊能夠按需加載,從而保證內核啓動時不用加載全部的模塊,即減小了內核的大小,也提升了效率。
經過編寫內核模塊來給內核增長功能或者接口是個很好的方式,既不用從新編譯內核,也方便調試和刪除。
2.1 內核模塊示例
2.1.1. 無參數的內核模塊
2.1.2. 帶參數的內核模塊
構造帶參數的內核模塊其實也不難,內核中已經提供了簡單的框架來給咱們聲明參數。
1. module_param(name, type, perm) : 定義一個模塊參數
+ 參數 name :: 既是用戶可見的參數名,也是模塊中存放模塊參數的變量名
+ 參數 type :: 參數的類型(byte, short, int, uint, long, ulong, charp, bool...) byte型存放在char變量中,bool型存放在int變量中
+ 參數 perm :: 指定模塊在 sysfs 文件系統中對應的文件權限(關於 sysfs 的內容後面介紹)
2. module_param_named(name, variable, type, perm) : 定義一個模塊參數,而且參數對內對外的名稱不同
+ 參數 name :: 用戶可見的參數名
+ 參數 variable :: 模塊中存放模塊參數的變量名
+ 參數 type和perm :: 同 module_param 中的 type 和 perm
3. module_param_string(name, string, len, perm) : 拷貝字符串到指定的字符數組
+ 參數 name :: 用戶可見的參數名
+ 參數 string :: 模塊中存放模塊參數的變量名
+ 參數 len :: string 參數的緩衝區長度
+ 參數 perm :: 同 module_param 中的 perm
4. module_param_array(name, type, nump, perm) : 定義數組類型的模塊參數
+ 參數 name :: 同 module_param 中的 name
+ 參數 type :: 同 module_param 中的 type
+ 參數 nump :: 整型指針,存放數組的長度
+ 參數 perm :: 同 module_param 中的 perm
5. module_param_array_named(name, array, type, nump, perm) : 定義數組類型的模塊參數,而且數組參數對內對外的名稱不同
+ 參數 name :: 數組參數對外的名稱
+ 參數 array :: 數組參數對內的名稱
+ 參數 type,nump,perm :: 同 module_param_array 中的 type,nump,perm
6. 參數描述宏
能夠經過 MODULE_PARM_DESC() 來給內核模塊的參數添加一些描述信息。
這些描述信息在編譯完內核模塊後,能夠經過 modinfo 命令查看。
2.2 內核模塊的位置
2.2.1. 內核代碼外
2.2.2. 內核代碼中
內核模塊的代碼也能夠直接放到內核代碼樹中。
編寫驅動的時候就能夠將完成此驅動功能的內核模塊加到內核代碼樹中 driver 的相應位置。
以後,在編譯內核的時候會將新的驅動之內核模塊的方式編譯出來。
2.3 內核模塊相關操做
2.3.1. 模塊安裝
make modules_install <-- 把隨內核編譯出來的模塊安裝到合適的目錄中
2.3.2. 模塊依賴性
linux中自動生產模塊依賴性的命令:
depmod <-- 產生內核依賴關係信息
depmod -A <-- 只爲新模塊生成依賴信息(速度更快)
2.3.3. 模塊的載入
內核模塊實驗時已經用過:
insmod module.ko
<-- 推薦使用如下的命令, 自動加載依賴的模塊
modprobe module [module parameters]
2.3.4. 模塊的卸載
內核模塊實驗時已經用過:
rmmod module.ko
<-- 推薦使用如下的命令, 自動卸載依賴的模塊
modprobe -r module
2.3.5. 模塊導出符號表
內核模塊被載入後,就動態的加載到內核中,爲了能讓其餘內核模塊使用其功能,須要將其中函數導出。
內核模塊中導出函數的方法:
EXPORT_SYMBOL(函數名) <-- 接在要導出的函數後面便可
EXPORT_SYMBOL_GPL(函數名) <-- 和EXPORT_SYMBOL同樣,區別在於只對標記爲GPL協議的模塊可見
3. 內核對象
2.6內核中增長了一個引人注目的新特性--統一設備模型(device model)。
統一設備模型的最初動機是爲了實現智能的電源管理,linux 內核爲了實現智能電源管理,須要創建表示系統中全部設備拓撲關係的樹結構,
這樣在關閉電源時,能夠從樹的節點開始關閉。
實現了統一設備模型以後,還給內核帶來了以下的好處:
1. 代碼重複最小化(統一處理的東西多了)
2. 能夠列舉系統中全部設備,觀察它們的狀態,並查看它們鏈接的總線
3. 能夠將系統中的所有設備以樹的形式完整,有效的展現出來--包括全部總線和內部鏈接
4. 能夠將設備和其對應的驅動聯繫起來,反之亦然
5. 能夠將設備按照類型加以歸類,無需理解物理設備的拓撲結構
6. 能夠沿設備樹的葉子向其根的反向依次遍歷,以保證能以正確的順序關閉設備電源
3.1 kobject 簡介
統一設備模型的核心部分就是 kobject,經過下面對kobject結構體的介紹,能夠大體瞭解它是如何使得各個物理設備可以以樹結構的形式組織起來的。
3.1.1. kobject
kobject 自己不表明什麼實際的內容,通常都是嵌在其餘數據結構中來發揮做用。嵌入了kobject以後,cdev設備之間就有了樹結構關係,cdev設備和其餘設備之間也有可層次關係。
3.1.2. ktype
ktype是爲了描述一族的kobject所具備的廣泛屬性,也就是將這一族的kobject的屬性統必定義一下,避免每一個kobject分別定義。
3.1.3. kset
kset是kobject對象的集合體,能夠全部相關的kobject置於一個kset之中,好比全部「塊設備」能夠放在一個表示塊設備的kset中。
3.1.4. kobject,ktype和kset之間的關係
這3個概念中,kobject是最基本的。kset和ktype是爲了將kobject進行分類,以便將共通的處理集中處理,從而減小代碼量,也增長維護性。
這裏kset和ktype都是爲了將kobject進行分類,爲何會有2中分類呢?
從整個內核的代碼來看,其實kset的數量是多於ktype的數量的,同一種ktype的kobject能夠位於不一樣的kset中。
作個不是很恰當的比喻,若是把kobject比做一我的的話,kset至關於一個一個國家,ktype則至關於人種(好比黃種人,白種人等等)。
人種的類型只有少數幾個,可是國家確有不少,人種的目的是描述一羣人的共通屬性,而國家的目地則是爲了管理一羣人。
一樣,ktype側重於描述,kset側重於管理。
3.1.5. kref
kref記錄kobject被引用的次數,當引用計數降到0的時候,則執行release函數釋放相關資源。
4. sysfs
sysfs是一個處於內存中的虛擬文件系統,它提供了kobject對象層次結構的視圖。
能夠用下面這個命令來查看 /sys 的結構
tree /sys # 顯示全部目錄和文件
或者
tree -L 1 /sys # 只顯示一層目錄