亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

第1個linux驅動___安裝驅動模塊之內核再愛我一次

原創(chuàng) 2016-11-16 09:51:10 562
摘要:通過Makefile編譯得到first_drv.ko文件,這是一個可以被安裝到ubuntu中的驅動模塊,要怎樣做呢?在/work/my_drivers/first_drv/1th/目錄下執(zhí)行:insmod first_drv.ko如果你是在普通用戶狀態(tài)下執(zhí)行的這條命令,可以看到系統提醒我們:insmod: error inserting 'first_drv.ko': -1 Ope

通過Makefile編譯得到first_drv.ko文件,這是一個可以被安裝到ubuntu中的驅動模塊,要怎樣做呢?

在/work/my_drivers/first_drv/1th/目錄下執(zhí)行:insmod first_drv.ko

如果你是在普通用戶狀態(tài)下執(zhí)行的這條命令,可以看到系統提醒我們:insmod: error inserting 'first_drv.ko': -1 Operation not permitted

這是因為安裝驅動模塊需要超級權限,你可以在普通用戶狀態(tài)下執(zhí)行:sudo insmod first_drv.ko,或直接切換到root用戶,執(zhí)行insmod first_drv.ko

回車后發(fā)現什么事都沒有發(fā)生,其實在我們執(zhí)行insmod first_drv.ko的時候,就相當于調用了first_drv.c中的module_init(first_drv_init),我們在以前的博文中說過module_init( )定義了一個結構體,當我們寫成module_init(first_drv_init)時,那個結構體中就會有一個函數指針指向了first_drv_init函數,從而跳轉執(zhí)行first_drv_init函數中的內容:

static int __init first_drv_init(void)
{   
    printk(KERN_INFO"hello world!\n");
    return 0;
}

容易得知,該函數被調用時會打印出"hello world!",但是如果我們分析的沒錯的話,為何剛剛又沒有看到命令行中輸出"hello world!"呢?

可能有同學會想是不是打印級別的原因,于是輸入cat /proc/sys/kernel/printk,


打?。?       4       1       7


第一個果然是4,當前打印級別"KERN_INFO"為6,因此改為7,即可讓"KERN_INFO"滿足打印出"hello world!"的打印級別,但事實上,即便改成7后,我們執(zhí)行insmod first_drv.ko后依舊看不出命令行中有任何動靜。

這是為什么呢?原來,ubuntu中嚴格限制printk輸出的數據顯示在命令行中,這內部有一套機制使得我們不論如何設置打印級別,也看不到"hello world!"。

但好在我們可以通過執(zhí)行dmesg命令來查看ubuntu隱藏起來的內核打印信息:


[   0.000000] Initializing cgroup subsys cpuset

[   0.000000] Initializing cgroup subsys cpu

···

[   0.000000] TSC: Frequency read from the hypervisor

[   0.000000] Detected 2501.000 MHz processor.

[   0.001144] Console: colour VGA+ 80x25

[  0.001146] console [tty0] enabled

···

[   2.665131] EXT4-fs: file extents enabled

[   2.666123] EXT4-fs: mballoc enabled

[   2.666135] EXT4-fs (sdb1): mounted filesystem with ordered data mode

[   2.737083] Installing knfsd (copyright (C) 1996 okir@monad.swb.de).

[   2.811797] eth4: link up

[   5.129212] svc: failed to register lockdv1 RPC service (errno 97).

[   5.129735] NFSD: Using /var/lib/nfs/v4recovery as the NFSv4 state recovery directory

[   5.129842] NFSD: starting 90-second grace period

[  14.218140] eth4: no IPv6 routers present

[ 979.436592] first_drv: module license 'unspecified' taints kernel.

[ 979.436620] Disabling lock debugging due to kernel taint

[ 979.437252] hello world!


最后三行打印信息是與我們安裝first_drv.ko驅動模塊相關的,我用紅色標注了,而最后一行打印信息便是我們夢寐以求的"hello world!",這正是我們安裝驅動模塊的過程中成功調用了first_drv_init函數的鐵證。

我們的驅動模塊很簡單,除了我們手寫的"hello world!"和"goodbye world..."外再也沒有可能打印別的了,那么倒數第3行和倒數第2行是怎么回事?

這是因為在安裝驅動模塊的過程中,系統找不到驅動程序的許可證信息,還記得我們之前說first_drv.c這個驅動還有一個不足之處嗎,這就是它的不足之處,這就好像是你經營一家餐館,但是沒有衛(wèi)生許可證,就算飯菜的味道再美味,顧客用餐還是會有點憂心忡忡。

其實說白了這種衛(wèi)生許可證只是一個形式,哪家的衛(wèi)生許可證都差不多,說到底這許可證和食物是否衛(wèi)生沒有必然的聯系,關鍵還是得看做飯菜的人有沒有注意衛(wèi)生。

我們的模塊許可證也是一樣,它與我們的程序沒有半點關系,程序寫得再糟糕,只要加個模塊許可證,內核便會一聲不吭地接納你,如果你代碼寫得再規(guī)范,唯獨丟了模塊許可證,那么內核還是會嘟嚷幾句:"first_drv: module license 'unspecified' taints kernel."、"Disabling lock debugging due to kernel taint",不過驅動模塊還是能夠工作的,但為了更加符合內核的要求,我們最好還是養(yǎng)成良好的習慣,加上模塊許可證,免得出現意想不到的麻煩。

我們只需要在first_drv.c最后再加一句:MODULE_LICENSE("GPL");即可。

符合內核規(guī)范的first_drv.c如下所示:

#include <linux/module.h> 
#include <linux/init.h>
 
static int __init first_drv_init(void)
{   
    printk(KERN_INFO"hello world!\n");
    return 0;
}
 
static int __exit first_drv_exit(void)
{   
    printk(KERN_INFO"goodbye world...\n");
    return 0;
}
 
module_init(first_drv_init);
module_exit(first_drv_exit);
 
MODULE_LICENSE("GPL");

執(zhí)行make重新編譯first_drv.c,新生成的first_drv.ko即可覆蓋舊的first_drv.ko,因此不必每次都執(zhí)行make clean刪除舊文件。

但是舊的first_drv.ko還安裝在內核上,在安裝新的first_drv.ko之前,我們如何卸載舊的first_drv.ko呢。

執(zhí)行l(wèi)smod可以查看ubuntu中已經安裝的驅動模塊,在打印出的一大頁信息的最上面可以看到:


Module                  Size  Used by

first_drv                1020  0 

binfmt_misc               8356  1 

nfsd                  241104  9 

exportfs                 4412  1 nfsd

nfs                   271880  0 

···

這說明first_drv驅動模塊還在內核中,我們需要使用rmmod命令來卸載它:

執(zhí)行sudo rmmod first_drv或者sudo rmmod first_drv.ko(在root用戶狀態(tài)下不需要加sudo)

回車后一樣沒有任何事情發(fā)生,執(zhí)行dmesg可以看到最后一行多了:


[ 2333.481131] goodbye world...


這正是first_drv_exit函數中打印的"goodbye world...",與講解insmod first_drv.ko是一樣的原理,執(zhí)行rmmod first_drv.ko時,就相當于去調用first_drv.c中的module_exit(first_drv_exit),然后調用first_drv_exit函數,打印出"goodbye world..."信息。

其實ubuntu每次只會對沒有許可證的驅動模塊發(fā)出一次警告打印信息,對于同一個沒有許可證的驅動,即便卸載該驅動再重裝,ubuntu也不會再打印任何警告信息,似乎有一種對該驅動“徹底失望”的意味,為了讓系統重新認識我們新的驅動程序,并確定在添加了許可證后內核不會再打印警告信息,我們可以將ubuntu重啟,重啟后,在該目錄下執(zhí)行sudo insmod first_drv.ko后,再執(zhí)行dmesg打印驅動安裝信息:


...

[  5.714574] svc: failed to register lockdv1 RPC service (errno 97).

[  5.715109] NFSD: Using /var/lib/nfs/v4recovery as the NFSv4 state recovery directory

[   5.715371] NFSD: starting 90-second grace period

[  14.690813] eth4: no IPv6 routers present

[  89.383529] hello world!


只打印了"hello world!",可以證明添加了驅動模塊的"GPL"許可證后,ubuntu內核已經完全認可了我們的驅動模塊first_drv。


發(fā)布手記

熱門詞條