Linux設備驅動程序學習(0)-Hello, world!模塊

當linux環境已經搭建好,就準備開始下一步的學習,linux設備驅動和內核。計劃按照LINUX設備驅動開發詳解一書的順序,一章一章學習。

一個學習Linux設備驅動程序都會碰到的第一個例程:
我將其複製到我的工作目錄,並編寫了一個簡單的Makefile文件:
make以後產生helloworld.ko驅動。
[root@localhost helloworld]# ls
helloworld.c   helloworld.ko     helloworld.mod.o  Makefile   Module.symvers
helloworld.c~  helloworld.mod.c  helloworld.o      Makefile~
[root@localhost helloworld]#
[root@localhost helloworld]# insmod helloworld.ko
[root@localhost helloworld]# dmesg
 [<c04744e9>] sys_open+0x1c/0x1e
 [<c0404f70>] syscall_call+0x7/0xb
 =======================
Hello world
Goodbye, world
Hello world
Goodbye, world
Hello world
[root@localhost helloworld]#
有些心得,網友總結的很好,搬過來了。
學習心得:
(1)驅動模塊運行在內核空間,運行時不能依賴於任何函數庫和模塊連接,所以在寫驅動時所調用的函數只能是作爲內核一部分的函數。
(2)驅動模塊和應用程序的一個重要不同是:應用程序退出時可不管資源釋放或者其他的清除工作,但模塊的退出函數必須仔細撤銷初始化函數所作的一切,否則,在系統重新引導之前某些東西就會殘留在系統中。
(3)處理器的多種工作模式(級別)其實就是爲了操作系統的用戶空間和內核空間設計的。在Unix類的操作系統中只用到了兩個級別:最高和最低級別。
(4)要十分注意驅動程序的併發處理。
(5)內核API中具有雙下劃線(_ _)的函數,通常是接口的底層組件,應慎用。
(6)
內核代碼不能實現浮點書運算。

(7)Makefile文件分析:
(8)insmod使用公共內核符號表來解析模塊中未定義的符號。公共內核符號表中包含了所有的全局內核項(即函數和變量的地址),這是實現模塊化驅動程序所必須的。
(9)Linux使用模塊層疊技術,我們可以將模塊劃分爲多個層,通過簡化每個層可縮短開發週期。如果一個模塊需要向其他模塊到處符號,則使用下面的宏:
符號必須在模塊文件的全局變量部分導出,因爲這兩個宏將被擴展爲一個特殊變量的聲明,而該變量必須是全局的。

(10)所有模塊代碼中都包含一下兩個頭文件:

(11)所有模塊代碼都應該指定所使用的許可證:

MODULE_LICENSE("Dual BSD/GPL");


此外還有可選的其他描述性定義:

MODULE_AUTHOR("");
MODULE_DESCRIPTION("");
MODULE_VERSION("");
MODULE_ALIAS("");
MODULE_DEVICE_TABLE("");


上述
MODULE_聲明習慣上放在文件最後。

(12)初始化和關閉
初始化的實際定義通常如下:

static int _ _init initialization_function(void)
{
/*初始化代碼*/
}

module_init(initialization_function)


清除函數的實際定義通常如下:

static int _ _exit cleanup_function(void)
{
/*清除代碼*/
}

module_exit(cleanup_function)


(13) Linux內核模塊的初始化出錯處理一般使用“goto”語句。通常情況下很少使用“goto”,但在出錯處理是(可能是唯一的情況),它卻非常有用。在大二學習C語言時,老師就建議不要使用“goto”,並說很少會用到。在這裏也是我碰到的第一個建議使用“goto”的地方。在追求效率的代碼中使用goto語句仍是最好的錯誤恢復機制。”--《Linux設備驅動程序(第3版)》以下是初始化出錯處理的推薦代碼示例:
(14)模塊參數:內核允許對驅動程序指定參數,而這些參數可在裝載驅動程序模塊時改變
以下是我的實驗程序:
實驗結果是 :
我這個實驗除了對參數的改變進行實驗外,我的一個重要的目的是測試“ module_param_array(TNparam , int , &TNparam_nr , S_IRUGO);”中&TNparam_nr對輸入參數數目的限制作用。經過我的實驗,表明&TNparam_nr並沒有對輸入參數的數目起到限制作用。真正起到限制作用的是static int TNparam[] = {1,2,3,4};本身定義的大小,我將程序進行修改:
static int TNparam[] = {1,2,3,4}; 
改爲 static int TNparam[] = {1,2,3,4,5,6,7,8};
其他都不變。

編譯後再進行實驗,其結果是:

[Tekkaman2440@SBC2440V4]#insmod hello-param.ko howmany=2 whom="KeKe" TNparam=4,3,2,1,5,6,7,8
(0) Hello, KeKe !
(1) Hello, KeKe !
TNparam[0] : 4
TNparam[1] : 3
TNparam[2] : 2
TNparam[3] : 1
TNparam[4] : 5
TNparam[5] : 6
TNparam[6] : 7
TNparam[7] : 8
[Tekkaman2440@SBC2440V4]#


(15)“#include <linux/sched.h>”  最重要的頭文件之一。包含驅動程序使用的大部分內核API的定義,包括睡眠函數以及各種變量聲明。

(16)
#include <linux/version.h>” 包含所構造內核版本信息的頭文件。

在學習過程中找到了幾篇很好的參考文檔:
(1)
第一章 模塊(Modules) URL:http://greenlinux.blogcn.com/diary,103232026.shtml
(2)《
從 2.4 到 2.6:Linux 內核可裝載模塊機制的改變對設備驅動的影響》
URL:http://www.ibm.com/developerworks/cn/linux/l-module26/
(3)《Linux2.6內核驅動移植參考》
URL:http://blog.chinaunix.net/u1/40912/showart_377391.html
發佈了12 篇原創文章 · 獲贊 0 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章