HelloWorld內(nèi)核
開始斷斷續(xù)續(xù)學(xué)習(xí)內(nèi)核,大概半年了,多少開始對內(nèi)核有點感悟了,但是對于這個龐然大物我顯得很渺小,在枯燥的內(nèi)核源碼之中似乎沒有一點點成功的喜悅,因此我選擇學(xué)習(xí)內(nèi)核模塊編程,通過編寫一些內(nèi)核模塊來體驗?zāi)且稽c點小小的成就感吧!
什么是內(nèi)核模塊
內(nèi)核模塊是具有獨立功能的程序。它可以被單獨編譯,但是不能單獨運行,它的運行必須被鏈接到內(nèi)核作為內(nèi)核的一部分在內(nèi)核空間中運行。
最簡單的內(nèi)核模塊
#include
一個Makefile來編譯這個內(nèi)核模塊
obj-m += hello-1.oall: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
注意:本文所有環(huán)節(jié)都是基于Centos6.5下測試OK,你可能在有的書上看見Makefile是這樣寫的
make -C /usr/src/linux-headers-$(shell uname -r) M=$(PWD) modules 其實/lib/modules/$(shell uname -r)/build 這個路徑就是上面路徑的一個軟鏈接 [root@localhost 2.6.32-431.el6.x86_64]# ls -al build lrwxrwxrwx. 1 root root 44 Mar 16 05:26 build -> /usr/src/kernels/2.6.32-504.12.2.el6.x86_64/
編寫好makefile文件后,使用make進(jìn)行編譯,編譯完就出現(xiàn)一個.ko的文件,這個就是內(nèi)核模塊,需要載入運行
載入內(nèi)核模塊進(jìn)行運行
載入內(nèi)核模塊的方法有很多比如: modprobe 和 insmod前者會分析模塊的依賴關(guān)系,并且會去指定路徑查找內(nèi)核模塊載入,而后者需要指定內(nèi)核模塊的絕對路徑進(jìn)行載入并且不解決模塊的依賴關(guān)系。這里我們使用insmod來載入內(nèi)核模塊,使用rmmod卸載內(nèi)核模塊 [root@localhost kernel_module]# insmod hello-1.ko使用dmes查看內(nèi)核模塊的輸出Hello world 1.卸載內(nèi)核模塊 [root@localhost kernel_module]# rmmod hello-1 dmesg查看輸出Goodbye world 1.
內(nèi)核模塊編程和應(yīng)用程序編程的異同
內(nèi)核模塊編程是不能去使用標(biāo)準(zhǔn)庫(比如malloc free等)和一些第三方的庫
內(nèi)核模塊編程是沒有內(nèi)存保護(hù)的,如果內(nèi)存訪問錯誤,就會出現(xiàn)oops錯誤
內(nèi)核模塊編程是沒有main函數(shù)的,只有一個初始化函數(shù),和一個提出函數(shù)
內(nèi)核模塊編程需要使用內(nèi)核提供的頭文件和API
內(nèi)核模塊編程的標(biāo)準(zhǔn)輸出是輸出到文件,而不是輸出到屏幕
內(nèi)核模塊編程的debug是不能使用gdb來進(jìn)行調(diào)試的。
內(nèi)核模塊進(jìn)階
內(nèi)核模塊的編程不僅僅是上面的一個HelloWorld,內(nèi)核模塊編程還有一些更高級的寫法,下面會一一介紹:
去掉init_module/cleanup_module
在上面的HelloWorld模塊中,你會發(fā)現(xiàn)初始化函數(shù)和退出函數(shù)好像是固定的名稱,那么有沒有辦法自己自定義名稱呢其實是可以的,你可以自己自定義名稱,然后進(jìn)行注冊即可(注冊其實就是做了一個函數(shù)指針的賦值而已)下面是自定義名稱的寫法:
//不需要固定內(nèi)核模塊的初始化函數(shù)的名字和結(jié)束的名字#include
__init/__initdata/__exit
在有的內(nèi)核模塊編程的書籍或者介紹內(nèi)核模塊編程的博客中,你或許會發(fā)現(xiàn)有這樣的一些特殊關(guān)鍵字__init ,_initdata ,__exit等等,其實這些都是gcc的擴(kuò)展屬性:__init宏最常用的地方是驅(qū)動模塊初始化函數(shù)的定義處,其目的是將驅(qū)動模塊的初始化函數(shù)放入名叫.init.text的輸入段。當(dāng)內(nèi)核啟動完畢后,這個段中的內(nèi)存會被釋放掉供其他使用。__initdata宏用于數(shù)據(jù)定義,目的是將數(shù)據(jù)放入名叫.init.data的輸入段。其它幾個宏也類似。
模塊描述信息
可以使用modinfo去查看一個模塊的模塊信息,下面是自己編寫的模塊和系統(tǒng)自帶的模塊的兩個模塊信息的對比
[root@localhost kernel_module]# modinfo hello-1.kofilename: hello-1.kosrcversion: 0D3956C127A907CC9E7114Fdepends: vermagic: 2.6.32-504.12.2.el6.x86_64 SMP mod_unload modversions [root@localhost kernel_module]# modinfo/lib/modules/2.6.32-431.el6.x86_64/kernel/fs/ext4/ext4.ko filename: /lib/modules/2.6.32-431.el6.x86_64/kernel/fs/ext4/ext4.kolicense: GPLdescription: Fourth Extended Filesystemauthor: Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others srcversion: 345EBDA2AEFF60FFED78864 depends: mbcache,jbd2 vermagic: 2.6.32-431.el6.x86_64 SMP mod_unload modversions
從上面的對比可知,自己編寫的模塊的模塊信息很少,沒有作者信息,沒有許可證信息等等,其實這些都可以設(shè)置
#include
模塊參數(shù)
在用戶態(tài)編寫程序的時候我們都應(yīng)該清楚,是可以給程序傳遞參數(shù)的,那么同樣內(nèi)核模塊同樣也有這樣的需求,下面的例子展示了如何去給內(nèi)核模塊傳遞參數(shù):
#include
模塊文件分割
在用戶態(tài)寫程序的時候,你會將一個大的程序分割成好幾個文件,這樣程序脈絡(luò)就顯的很清晰。在這里我們將初始化函數(shù)和退出函數(shù)分開在兩個文件中編寫。
start.c中#include
-
helloworld
+關(guān)注
關(guān)注
0文章
13瀏覽量
4601 -
內(nèi)核模塊
+關(guān)注
關(guān)注
0文章
10瀏覽量
3504
原文標(biāo)題:黑客內(nèi)核:編寫屬于你的Hello world
文章出處:【微信號:C_Expert,微信公眾號:C語言專家集中營】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
linux 了解內(nèi)核模塊的原理 《Rice linux 學(xué)習(xí)開發(fā)》

Linux 內(nèi)核模塊工作原理及內(nèi)核模塊編譯案例

詳解Linux內(nèi)核模塊的編寫方法
Linux內(nèi)核模塊間通訊方法

Linux內(nèi)核模塊程序結(jié)構(gòu)
高效學(xué)習(xí)Linux內(nèi)核——內(nèi)核模塊編譯
什么是內(nèi)核模塊?如何編寫一個簡單的模塊?
什么是 Linux 內(nèi)核模塊?
嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊調(diào)試教程

如何在Petalinux創(chuàng)建Linux內(nèi)核模塊?
嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊調(diào)試

評論