學習Linux內核模塊編寫總結

在學習編寫Linux內核模塊的時候我們首先要清楚的知道內核模塊的作用,爲什麼要使用內核模塊?這是因爲Linux內核的整體結構非常的龐大,包含的組件也非常的多,把所有的內核模塊都編譯到Linux內核,會導致的問題是內核很大,同時在現有的內核新增或刪除部分功能時,不得不重新編譯內核,可謂相當的費時。而模塊的使用就是爲了解決這一問題,即動態的在內核中添加或者刪除相應功能。下面以一個經典的代碼來看是相關的分析:

#include
#include

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("xxx");
MODULE_DESCRIPTION("Hello World Module");
MODULE_ALIAS("a simplest module");

static int __init hello_init()
{
    printk(KERN_EMERG"Hello World!/n");  //注意比較兩種printk( )參數的不同之處
    return 0;                                                     //即優先級的用法
}

static void __exit hello_exit()
{
    printk("<6>hello exit/n");
}

module_init(hello_init);
module_exit(hello_exit);
在閱讀相關的代碼時我們的入口點不再是main( )函數,而應該是module_init( 函數名 )函數;細心的話就會發現在hello_init()函數前面有一個__init ,它的作用是在連接的時候把標識的函數放在 .init.text這個區段內。此外所有的__init函數在區段 .initcall.init中還保存了一個函數指針,在初始化的時候內核會通過這些函數指針調用這些__init 函數,在完成初始化後釋放掉該區段。

printk( )函數和平printf( )函數類似,但是printk( )函數有打印優先級(數值越低,優先級越高),如果這個打印優先級比默認的低,那麼將看不到輸出,所以在使加載和卸載模塊的過程中如果看不到打印語句,這是一個值得分析的問題。查看默認優先級的語句爲:cat    /proc/sys/kenel/printk

在代碼的起始部分我們給出瞭如下代碼:

1.  MODULE_LICENSE("Dual BSD/GPL");
2.  MODULE_AUTHOR("xxx");
3.  MODULE_DESCRIPTION("Hello World Module");
4.  MODULE_ALIAS("a simplest module");

1.爲必須選擇的語句,它是模塊的許可權限,如果不聲明,會出現警告信息。

2.3.4爲可選項,其爲模塊的一些相關信息。如作者、實現的功能等。

最後自然到了module_exit(hello_exit),有加載必須要有卸載,呵呵……做事要有始有終嘛,所以這自然就是相關的卸載部分了。其中的printk( )和前面的分析完全一樣。

外加一點,如果模塊有參數的傳遞,那麼還需使用module_param(參數名,參數類型,參數的讀/寫權限),當參數爲數組時,使用module_param_array(數組名,數組類型,數組長,參數讀/寫權限)。

懂了模塊的編寫,接下來就應該是模塊的編譯了,在當前路徑下建立一個Makefile文件,編寫如下代碼:

ifneq ($(KERNELRELEASE),)

obj-m := hello.o           //hello爲你編寫的模塊代碼保存名(在此保存的爲hello.c) ,編譯生成目標文件hello.o

else
 
KDIR := /lib/modules/2.6.18-53.el5/build    //KDIR是本Makefile 依賴的linux內核源碼路徑  ,如是交叉編譯時就取開發板上運行的源碼路徑
all:
 make -C $(KDIR) M=$(PWD) modules

 //到linux源碼所在的目錄執行主Makefile 並當前路徑傳給主Makefile,告訴主Makefile執行完後返回到當前目錄,執行Makefile,
clean:
 rm -f *.ko *.o *.mod.o *.mod.c *.symvers

endif

KERNELRELEASE是在內核源碼的頂層Makefile中定義的一個變量,在第一次讀取執行此Makefile時, KERNELRELEASE沒有被定義,所以make將讀取執行else之後的內容。如果make的目標是clean,直接執行clean操作,然後結束。當make的目標爲all時,-C $(KDIR) 指明跳轉到內核源碼目錄下讀取那裏的Makefile;M=$(PWD) 表明然後返回到當前目錄繼續讀入、執行當前的Makefile。當從內核源碼目錄返回時,KERNELRELEASE已被被定義,kbuild也被啓動去解析kbuild語法的語句,make將繼續讀取else之前的內容。else之前的內容爲kbuild語法的語句, 指明模塊源碼中各文件的依賴關係,以及要生成的目標模塊名。

該Makefile(注意Makefile中的M要大寫,具體原因自己可查資料,在次就不一一講解了)的編寫一般都具有固定的格式,變化很少,可以當成模板來記。

最後通過insmod   hello.ko 和 rmmod   hello就可實現模塊的安裝和卸載了!!!

O(∩_∩)O~  最後總結一句:燈籠是張紙,只要你多思考多動手就OK了。

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