Linux的模塊驅動 函數
這是個最簡單的驅動程序。就是打印hello的信息。驅動程序和咱們的程序語言結果有點不大同樣。驅動模塊的入口是倒數第二行的module_init()的函數。驅動模塊的出口是module_exit()的函數。 spa
3.接着是makfile文件:命令行
這也是一個很簡單的Makefile文件了。Obj-m後面跟的是咱們的最終目標依賴的文件hello.o。第三行的KDIR是咱們編譯進的內核的路徑。All是執行make獲得的目標,$(KDIR)指定內核的路徑,就是第三行的路徑。M=$(PWD)是模塊存放的路徑。接着就是清除生成的文件的命令。 3d
4.make的執行過程: blog
從上面的執行的過程,咱們能夠看到makefile的執行的過程。 字符串
若是在一個工程裏,當有兩個.c文件的時候的編寫: it
Hello.c: io
Function.c: 編譯
Makefile修改成: function
最後編譯的結果以下圖:
內核模塊的安裝和卸載:
insmod hello.ko
卸載內核模塊:
rmmod hello(卸載的時候不用加.ko)
查看模塊:
lsmod
執行的結果:
注意:內核模塊只有當沒有用戶用時才能夠卸載,如上圖:咱們的test是沒有被使用,而fuse有兩個用戶在使用。咱們試着卸載這兩個內核模塊的截圖:
內核模塊的可選的信息:模塊申明、模塊參數、符號信息。
模塊的申明:
MODULE_LICENSE("遵照的協議")
申明該模塊遵照的許可證協議,如:"GPL"、"GPL v2"等。
MODULE_AUTHOR("做者")
申明模塊的做者
MODULE_DESCRIPTION("該模塊的功能描述")
MODULE_VERSION("v1.0")
申明模塊的版本
模塊申明可讓讀者知道該模塊所遵照的協議,增長模塊代碼的可讀性。
只是一個提示,增長可讀性的做用。
模塊參數的傳遞:
在咱們的應用程序中:int main(int argc,char** argv):argc表示命令行輸入的參數個數,argv中保存輸入端的參數。
那麼咱們的內核模塊中是怎麼傳入參數的呢?:
模塊參數跟咱們程序語言的參數有點不大同樣,除了用通常的數據類型來申明變量參數,咱們還得用module_param()這個宏來指定它是模塊參數:
Module_param(name,type,perm):
Name:變量的名稱
Type:變量的類型,bool,int,charp。
Perm:訪問權限。S_IRUGO:讀權限。S_IWUSR:寫權限。
例如:
Int a=33;
Char *st;
Module_param(a,int ,S_IRUGO);
Module_param(st,charp,S_IRUGO);
下面是執行的實例:
咱們定義了一個a=99;而後在14行打印出來。運行的結果:
上面是執行的過程,咱們也能夠在執行的時候給它加參數:
字符串也是同樣:
運行的結果:
最後是符號導出:
符號導出的實例:
修改Makefile:
修改function.c爲:
執行的過程:
同時產生了兩個.ko模塊。
當咱們去安裝hello.ko的時候,出現了這個錯誤:未定義的符號:
這是由於咱們程序中的extern int function();如今的系統中不存在這個函數。那是否是得先insmod function.ko呢!?
雖然系統已經出現了function函數,但是系統仍是找不到。能夠看出錯誤依然存在。
這就是模塊導出的問題:當咱們要去使用一個模塊裏面的變量,函數的時候,必須使用符號導出。也就是把變量和函數輸出到咱們的系統當中,使整個系統均可以使用。
修改function.c爲:
用EXPORT_SYMBOL()來申明,個人function是能夠被系統的其餘模塊使用的。不過,咱們應該先編譯function.ko,在編譯hello.ko。結果:
這就是符號輸出的使用。
總結與應用程序的區別:
內核的打印:
Printf和printk都是打印信息的。可是printk還有級別打印:
Hello.c:
輸出結果:
結果只有KERN_EMERG級別的纔在屏幕打印出來。這樣的打印級別,咱們能夠控制在那些地方能夠打印什麼。固然,咱們也能夠用輸入來代替級別。例如上面的"<0>",就是KERN_EMER。