内核模块化编程
目錄
內核模塊的概念介紹
動態模塊化編程框架
模塊加載函數
模塊卸載函數
模塊的開源協議與聲明
模塊編譯 Makefile 模板
單模塊的編程步驟
1 編寫內核模塊文件test.c
2 編寫Makefile
3 編譯生成test.ko
內核模塊的概念介紹
Linux 內核整體結構已經很龐大,包含了很多的組件,而對于我們工程師而言,有兩種方法將需要的功能包含進內核當中。
????????一:將所有的功能都編譯進 Linux 內核(靜態加載模塊)。
????????二:將需要的功能編譯成模塊,在需要的時候動態地添加(動態加載模塊)。
上述兩種方式優缺點分析:
????????第一種:優點:不會有版本不兼容的問題,不需要進行嚴格的版本檢查缺點:生成的內核會很大;要在現有的內核中添加新的功能,則要編譯整個內核
????????第二種:優點:模塊本身不編譯進內核,從而控制了內核的大小;模塊一旦被加載,將和其它的部分完全一樣。缺點:可能會有內核與模塊版本不兼容的問題,導致內核崩潰;會造成內存的利用率比較低。
在超級終端MobaXterm 使用模塊常用命令
#insmod xxx.ko//將模塊添加進內核 #rmmod xxx.ko//將模塊從內核卸載 #lsmod //查看已安裝到內核的模塊 #modprobe //載入指定的個別模塊,或是載入一組相依賴的模塊。 modprobe 會根據 depmod 所 //產生的依賴關系,決定要載入哪些模塊。若在載入 過程中發生錯誤,在 modprobe 會卸載整 //組的模塊。依賴關系是通過讀取 /lib/modules/2.6.xx/modules.dep 得到的。而該文件是通過 //depmod 所建立。 #modinfo //查看模塊信息。使用方法: #modinfo XXX.ko #tree –a //查看當前目錄的整個樹結構動態模塊化編程框架
模塊加載函數
static int __init XXX_init(void)//加載函數 {//注冊設備helloreturn 0; } moudle_init(XXX_init); // 當執行#insmod 或者#modprobe 時調用,可以看作模塊的入口????????當#insmod xxx.ko時會調用 module_init所修飾的 XXX_init函數來完成一些初始化操作(xxx在寫代碼時要根據實際模塊進行修改)Linux 內核的模塊加載函數一般用__init 標識聲明,用于告訴編譯器相關函數或變量僅用于初始化,初始化結束后就釋放這段內存。XXX_init 函數的返回值為一個整形的數,如果執行成功,則返回 0,初始化失敗時則返回錯誤編碼, Linux 內核當中的錯誤編碼是負值,在<linux/errno.h>中定義
模塊卸載函數
static void __exit XXX_exit(void) { } moudle_exit(XXX_exit); // 執行#rmmod 時調用????????在用 rmmod 或 modprobe 命令卸載模塊時,該函數被執行。完成與加載相反的工作。模塊的卸載函數和模塊加載函數實現相反的功能,主要包括:
1) 若模塊加載函數注冊了 XXX,則模塊卸載函數注銷 XXX
2) 若模塊加載函數動態分配了內存,則模塊卸載函數釋放這些內存
3) 若模塊加載函數申請了硬件資源,則模塊卸載函數釋放這些硬件資源
4) 若模塊加載函數開啟了硬件資源,則模塊卸載函數一定要關閉這些資源
模塊的開源協議與聲明
MODULE_LICENSE("GPL");GPL 協議介紹:全稱為 GNU General Public Licence, GPL 保證了所有開發者的權利(開發者擁有版權和專利),同時為使用者提供了足夠的復制、分發和修改的權利:
1)使用者可以自由復制軟件到任何地方
2) 使用者可自由分發源代碼或者二進制文件
3) 使用者可以用來盈利, 但必須想客戶提供該軟件的 GNU GPL 許可協議,以便讓他們知道,他們可以從別的渠道免費得到這份軟件,以及你收費的理由
4) 使用者可自由修改軟件,如果使用者想添加或刪除某個功能,沒問題,如果你想在別的項目中使用部分代碼,也沒問題,唯一的要求是,使用了這段代碼的項目也必須使用 GPL協議
非必須的模塊聲明
MODULE_AUTHOR // 聲明作者 MODULE_DESCRIPTION // 對模塊簡單的描述 MODULE_VERSION // 聲明模塊的版本 MODULE_ALIAS // 模塊的別名 MODULE_DEVICE_TABLE // 告訴用戶空間這個模塊所支持的設備模塊編譯 Makefile 模板
# Makefile 2.6 模板 #當make的目標為all時,-C $(KDIR) 指明跳轉到內核源碼目錄下讀取那里的Makefile; #obj-m表示把文件hello.o作為"模塊"進行編譯,不會編譯到內核,但是會生成一個獨立的 "hello.ko" 文件; #M=$(PWD) 表明然后返回到當前目錄繼續讀入、執行當前的Makefile。 obj-m += hello.o #在使用時KDIR要修改為你自己的內核的頂級目錄 KDIR:= /3linux/linux-3.5 all:make -C $(KDIR) M=$(PWD) modules #-C 選項的作用是指將當前工作目錄轉移到你所指定的位置。 #“M=”選項的作用是,當用戶需要以某個內核為基礎編譯一個外部模塊的話, #需要在make modules 命令中加入“M=dir”, #程序會自動到你所指定的dir目錄中查找模塊源碼,將其編譯,生成KO文件。 clean:rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.markers *.order #使用make命令編譯模塊,由于makefile文件無法正確的處理帶空格的路徑名, #確保路徑沒有空格符 #該命令是make modules命令的擴展,-C選項的作用是指將當前的工作目錄轉移到制定的 目錄,即(KDIR)目錄,程序到(shellpwd)當前目錄查找模塊源碼,將其編譯,生成.ko文件單模塊的編程步驟
1 編寫內核模塊文件test.c
#include<linux/kernel.h> #include<linux/module.h> static int __init test_init(void) //加載函數 {printk("this is test file!\n");return 0; } static void __exit test_exit(void) //卸載函數 {printk("exit!\n"); } module_init(test_init); //聲明加載函數 module_exit(test_exit); //聲明卸載函數 MODULE_LISENSE("GPL"); //聲明開源協議2 編寫Makefile
obj-m += test.o KDIR:=/root/tiny4412/linux-3.5/all:make -C $(KDIR) M=$(PWD) modules clean:rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.markers *.order3 編譯生成test.ko
在虛擬機終端中輸入命令make,生成模塊文件test.ko。將 test.ko 拷貝到根文件系統,在開發板的終端中執行
insmod test.ko //加載test模塊 lsmod //查看當前掛載模塊 rmmod test.ko //卸載test模塊總結
- 上一篇: 简单的UDP监听需要打开w网路岗才能接收
- 下一篇: 微信表情和emoji对应代码