第1个linux驱动___安装驱动模块之内核再爱我一次

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第1个linux驱动___安装驱动模块之内核再爱我一次相关的知识,希望对你有一定的参考价值。

在上一篇博文中,我们已经通过Makefile编译得到first_drv.ko文件,这是一个可以被安装到ubuntu中的驱动模块,要怎样做呢?


在/work/my_drivers/first_drv/1th/目录下执行:insmod first_drv.ko


如果你是在普通用户状态下执行的这条命令,可以看到系统提醒我们:insmod: error inserting ‘first_drv.ko‘: -1 Operation not permitted


这是因为安装驱动模块需要超级权限,你可以在普通用户状态下执行:sudo insmod first_drv.ko,或直接切换到root用户,执行insmod first_drv.ko


回车后发现什么事都没有发生,其实在我们执行insmod first_drv.ko的时候,就相当于调用了first_drv.c中的module_init(first_drv_init),我们在以前的博文中说过module_init( )定义了一个结构体,当我们写成module_init(first_drv_init)时,那个结构体中就会有一个函数指针指向了first_drv_init函数,从而跳转执行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       4       1       7


第一个果然是4,当前打印级别"KERN_INFO"为6,因此改为7,即可让"KERN_INFO"满足打印出"hello world!"的打印级别,但事实上,即便改成7后,我们执行insmod first_drv.ko后依旧看不出命令行中有任何动静。


事实上是这样的,ubuntu中严格限制printk输出的数据显示在命令行中,这内部有一套机制使得我们不论如何设置打印级别,也看不到"hello world!"。


但好在我们可以通过执行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 [email protected]).

[   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这个驱动还有一个不足之处吗,这就是它的不足之处,这就是好像你经营一家餐馆,但是没有卫生许可证,就算饭菜的味道再美味,顾客用餐还是会有点忧心忡忡。


其实说白了这种许可证只是一个形式,哪家的许可证都差不多,说到底许可证和食物是否卫生没有必然的联系,关键还是得看做饭菜的人有没有注意卫生。


我们的模块许可证也是一样,和我们的程序没有半点关系,程序写得再糟糕,只要加个模块许可证,内核会一声不吭地就接纳你,如果你代码写得再规范,唯独丢了模块许可证,那么内核还是会嘟嚷几句:"first_drv: module license ‘unspecified‘ taints kernel."、"Disabling lock debugging due to kernel taint",但驱动模块还是能够工作的,但为了更加符合内核的要求,我们最好还是养成良好的习惯,加上模块许可证,免得出现意想不到的麻烦。


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


符合内核规范的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");


执行make重新编译first_drv.c,新生成的first_drv.ko即可覆盖旧的first_drv.ko,因此不必每次都执行make clean删除旧文件。


但是旧的first_drv.ko还安装在内核上,在安装新的first_drv.ko之前,我们如何卸载旧的first_drv.ko呢。


执行lsmod可以查看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命令来卸载它:


执行sudo rmmod first_drv或者sudo rmmod first_drv.ko(在root用户状态下不需要加sudo)


回车后一样没有任何事情发生,执行dmesg可以看到最后一行多了:


[ 2333.481131] goodbye world...


这正是first_drv_exit函数中打印的"goodbye world...",与讲解insmod first_drv.ko时一样的原理,执行rmmod first_drv.ko时,就相当于去调用first_drv.c中的module_exit(first_drv_exit),然后调用first_drv_exit函数,打印出"goodbye world..."信息。


其实ubuntu每次只会对没有许可证的驱动模块发出一次警告打印信息,对于同一个没有许可证的驱动,即便卸载再重装,ubuntu就再也不会打印警告信息,有一种对该驱动程序“彻底失望”的意味,为了让系统重新认识我们新的驱动程序,并确定在添加了许可证后内核不会再打印警告信息,我们将ubuntu重启,重启后,在该目录下执行sudo insmod first_drv.ko后,再执行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。

本文出自 “12253782” 博客,请务必保留此出处http://12263782.blog.51cto.com/12253782/1873267

以上是关于第1个linux驱动___安装驱动模块之内核再爱我一次的主要内容,如果未能解决你的问题,请参考以下文章

第1个linux驱动___打印"hello world"

第1个linux驱动___打印"hello world"

第1个linux驱动___给驱动模块上户口

第1个linux驱动___给驱动模块上户口

001_linux驱动之_驱动的加载和卸载

第1个linux驱动___投靠NFS网络文件系统