模块(module)是在内核空间运行的程序,实际上是一种目标对象文件,没有链接,不能独立运行,但是可以装载到系统中作为内核的一部分运行,从而可以动态扩充内核的功能。模块最主要的用处就是用来实现设备驱动程序。使用模块的优点: 1,将来修改内核时,不必全部重新编译整个内核,可节省不少时间 ;2,系统中如果需要使用新模块,不必重新编译内核,只要插入相应的模块即可。这两点对于内核开发尤为有用,那么下面我们就简单学习以下module的编写方法。以一个完整的“Hello word”模块为例。
首先实现的是具体的代码部分:
这个模块中定义了两个函数,其中hello_init在模块装载到内核时调用,而hello_exit在模块被移除时调用。module_init与module_exit使用了内核特殊宏来表示上述两个函数说扮演的角色。而MODULE_LICENSE用来告诉内核该模块所采用的自由许可证。
(资料图片仅供参考)
有了代码后我们还需要将其编译成模块,这个时候就需要用到Makefile,Makefile的具体内容如下:
Makefile中内容的含下次学习,将两个文件放到同一个目录下,执行make命令,执行完后就会生成一个ko文件,这个ko文件就是我们需的module。
有了这个ko,我们就可以将其加载到Linux内核中了,不过需要注意的是,加载与卸载内核模块都需要使用root权限。
加载内核使用的是insmod命令:
一般情况下,没异常打印就表示加载成功了,但为了确认我们可以使用lsmod命令查看内核中已加载的module:
通过这个命令我们果断看到了我们所希望的helloModule这个模块。此时我们就可以通过modinfo这个命令查看到这个module的信息了:
那如果此时我们不再需要这个模块了我们则可以通过rmmod这个命令将其从内核中卸载:
但我们发现无论加载还是卸载模块,我们都没有看到printk中的打印,这主要是printk会根据日志打印级别来决定时候把消息打印到当前控制台上,决定的因素是日志级别时候小于console_loglevel值,那我们是不是就无法看到这个打印了吗,当然不是,我们可以通过dmesg查看到:
这里由于我实上次,所以我们看到了上次打印。