5、Linux内核模块开发
Linux的模塊驅(qū)動
?
這是個最簡單的驅(qū)動程序。就是打印hello的信息。驅(qū)動程序和我們的程序語言結(jié)果有點(diǎn)不大一樣。驅(qū)動模塊的入口是倒數(shù)第二行的module_init()的函數(shù)。驅(qū)動模塊的出口是module_exit()的函數(shù)。
3.接著是makfile文件:
這也是一個很簡單的Makefile文件了。Obj-m后面跟的是我們的最終目標(biāo)依賴的文件hello.o。第三行的KDIR是我們編譯進(jìn)的內(nèi)核的路徑。All是執(zhí)行make得到的目標(biāo),$(KDIR)指定內(nèi)核的路徑,就是第三行的路徑。M=$(PWD)是模塊存放的路徑。接著就是清除生成的文件的命令。
4.make的執(zhí)行過程:
從上面的執(zhí)行的過程,我們可以看到makefile的執(zhí)行的過程。
?
?
?
如果在一個工程里,當(dāng)有兩個.c文件的時(shí)候的編寫:
Hello.c:
Function.c:
Makefile修改為:
最后編譯的結(jié)果如下圖:
?
?
?
?
?
內(nèi)核模塊的安裝和卸載:
insmod hello.ko
卸載內(nèi)核模塊:
rmmod hello(卸載的時(shí)候不用加.ko)
查看模塊:
lsmod
?
執(zhí)行的結(jié)果:
注意:內(nèi)核模塊只有當(dāng)沒有用戶用時(shí)才可以卸載,如上圖:我們的test是沒有被使用,而fuse有兩個用戶在使用。我們試著卸載這兩個內(nèi)核模塊的截圖:
?
?
?
內(nèi)核模塊的可選的信息:模塊申明、模塊參數(shù)、符號信息。
模塊的申明:
????MODULE_LICENSE("遵守的協(xié)議")
申明該模塊遵守的許可證協(xié)議,如:"GPL"、"GPL v2"等。
????MODULE_AUTHOR("作者")
????申明模塊的作者
????MODULE_DESCRIPTION("該模塊的功能描述")
????MODULE_VERSION("v1.0")
申明模塊的版本
?
模塊申明可以讓讀者知道該模塊所遵守的協(xié)議,增加模塊代碼的可讀性。
?
?
只是一個提示,增加可讀性的作用。
?
模塊參數(shù)的傳遞:
在我們的應(yīng)用程序中:int main(int argc,char** argv):argc表示命令行輸入的參數(shù)個數(shù),argv中保存輸入端的參數(shù)。
那么我們的內(nèi)核模塊中是怎么傳入?yún)?shù)的呢?:
?
模塊參數(shù)跟我們程序語言的參數(shù)有點(diǎn)不大一樣,除了用一般的數(shù)據(jù)類型來申明變量參數(shù),我們還得用module_param()這個宏來指定它是模塊參數(shù):
Module_param(name,type,perm):
Name:變量的名稱
Type:變量的類型,bool,int,charp。
Perm:訪問權(quán)限。S_IRUGO:讀權(quán)限。S_IWUSR:寫權(quán)限。
例如:
Int a=33;
Char *st;
Module_param(a,int ,S_IRUGO);
Module_param(st,charp,S_IRUGO);
?
下面是執(zhí)行的實(shí)例:
我們定義了一個a=99;然后在14行打印出來。運(yùn)行的結(jié)果:
上面是執(zhí)行的過程,我們也可以在執(zhí)行的時(shí)候給它加參數(shù):
字符串也是一樣:
運(yùn)行的結(jié)果:
?
?
最后是符號導(dǎo)出:
符號導(dǎo)出的實(shí)例:
修改Makefile:
?
修改function.c為:
?
執(zhí)行的過程:
?
同時(shí)產(chǎn)生了兩個.ko模塊。
當(dāng)我們?nèi)グ惭bhello.ko的時(shí)候,出現(xiàn)了這個錯誤:未定義的符號:
這是因?yàn)槲覀兂绦蛑械膃xtern int function();現(xiàn)在的系統(tǒng)中不存在這個函數(shù)。那是不是得先insmod function.ko呢!?
雖然系統(tǒng)已經(jīng)出現(xiàn)了function函數(shù),可是系統(tǒng)還是找不到。可以看出錯誤依然存在。
?
這就是模塊導(dǎo)出的問題:當(dāng)我們要去使用一個模塊里面的變量,函數(shù)的時(shí)候,必須使用符號導(dǎo)出。也就是把變量和函數(shù)輸出到我們的系統(tǒng)當(dāng)中,使整個系統(tǒng)都可以使用。
修改function.c為:
用EXPORT_SYMBOL()來申明,我的function是可以被系統(tǒng)的其他模塊使用的。不過,我們應(yīng)該先編譯function.ko,在編譯hello.ko。結(jié)果:
這就是符號輸出的使用。
總結(jié)與應(yīng)用程序的區(qū)別:
內(nèi)核的打印:
Printf和printk都是打印信息的。但是printk還有級別打印:
Hello.c:
?
輸出結(jié)果:
結(jié)果只有KERN_EMERG級別的才在屏幕打印出來。這樣的打印級別,我們可以控制在那些地方可以打印什么。當(dāng)然,我們也可以用輸入來代替級別。例如上面的"<0>",就是KERN_EMER。
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/FORFISH/p/5188421.html
總結(jié)
以上是生活随笔為你收集整理的5、Linux内核模块开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 7个你可能不认识的CSS单位
- 下一篇: linux 其他常用命令