一:機制與策略(轉)html
http://www.51hei.com/bbs/dpj-29441-1.htmllinux
機制mechanism,策略policy。若是你看過《linux device drivers》,裏面給出了大概的介紹。機制提供了幹什麼(do what),策略提供如何作(how to do)。驅動程序完成機制的功能,把策略的實現留給用戶的應用程序。編程
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------數據結構
二:用戶空間和內核空間併發
一個模塊在內核空間運行, 而應用程序在用戶空間運行. 這個概念是操做系統理論的基礎,函數
驅動模塊試涉及到內核態以及用戶態,當應用程序發出一個systerm call或者被硬件的中斷掛起,內核在上下文中執行systerm call(系統調用),內核和應用程序的memory map也不一樣,因此this
內核的內存空間以及應用程序的內存空間不能互相訪問,要用到copy_to_user 以及copy_from_user函數;spa
內核程序與應用程序最大的不一樣是內核是併發的,而應用程序是按順序執行的;因此應用程序不用擔憂上線文切換,而內核必需要作好上下文切換;操作系統
2.6內核之後,內核是搶佔式的,這必需要求內核代碼是可重入的code
內核的棧是很是小的,內核共用4k的棧,因此當須要大的結構體時,是使用堆內存;kzalloc
驅動模塊的代碼中的函數以及數據結構跟內核的版本緊密相連,因此編譯模塊的時候要選用正確的內核版本,安裝模塊的時候也要選擇正確的內核版本;
若是
2.6 預備知識
#include <linux/module.h> 包含大量的模塊加載卸載的頭文件 如module_init 、module_exit等函數
#include <linux/init.h> 指定清理的初始化函數,init的初始化函數
MODULE_LICENSE("GPL"); 內核認識的特定許可有, "GPL"( 適用 GNU 通用公共許可的任何版本 ),
MODULE_AUTHOR ( 聲明誰編寫了模塊 ),
MODULE_DESCRIPION( 一我的可讀的關於模塊作什麼的聲明 ),
MODULE_VERSION ( 一個代碼修訂版本號
MODULE_ALIAS ( 模塊爲人所知的另外一個名子 )
以及 MODULE_DEVICE_TABLE ( 來告知用戶空間, 模塊支持那些設備 ).
2.7 初始化中的錯誤處理
這點很重要,好比你在insmodu 一個模塊的時候加載失敗,若是這個驅動模塊的代碼沒有進行相關錯誤處理,在加載會出現更多問題
錯誤恢復是最好使用goto語句;
1 int __init my_init_function(void) 2 { 3 int err; 4 err = register_this(ptr1, "skull"); /* registration takes a pointer and a name */
5 if (err) 6 goto fail_this; 7 err = register_that(ptr2, "skull"); 8 if (err) 9 goto fail_that; 10 err = register_those(ptr3, "skull"); 11 if (err) 12 goto fail_those; 13 return 0; /* success */
14 fail_those: 15 unregister_that(ptr2, "skull"); 16 fail_that: 17 unregister_this(ptr1, "skull"); 18 fail_this: 19 return err; /* propagate the error */
20 }
或者在失敗的時候直接執行你的清理函數便可,可是這樣須要更多的上下文切換,消耗更過的內存空間,寄存器等;或者能夠下下面一個函數;
檢查每種操做的狀態,在清理,可是這樣作的壞處是須要定義不少歌變量,仍是用goto比較好;
1 struct something *item1; 2 struct somethingelse *item2; 3 int stuff_ok; 4 void my_cleanup(void) 5 { 6 if (item1) 7 release_thing(item1); 8 if (item2) 9 release_thing2(item2); 10 if (stuff_ok) 11 unregister_stuff(); 12 return; 13 }
1 int __init my_init(void) 2 { 3 int err = -ENOMEM; 4 item1 = allocate_thing(arguments); 5 item2 = allocate_thing2(arguments2); 6 if (!item2 || !item2) 7 goto fail; 8 err = register_stuff(item1, item2); 9 if (!err) 10 stuff_ok = 1; 11 else
12 goto fail; 13 return 0; /* success */
14 fail: 15 my_cleanup(); 16 return err; 17 }