文章目录
参考书籍:LDD3
linux内核版本:3.3
Linux 允许在系统运行时加载或者去除一块内核代码,称为一个内核模块。模块化的设计可以使linux内核镜像尽可能的小,同时又方便对新功能进行调试。也能实现设备的热插拔。
模块和应用程序的不同之处在于,模块只是提供服务给应用程序调用,有点类似库。模块也不能调用C库,但linux会提供相应的函数。模块去除的时候必须清理掉初始化时做的事情,如申请内存,注册设备等等。
最简单的内核模块例子
#include <linux/init.h>
#include <linux/module.h>
static int __init test_init(void)
{
printk(KERN_ALERT "hello kernel!\n");
return 0;
}
static void __exit test_exit(void)
{
printk(KERN_ALERT "exit kernel!\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("HGL");
#include <linux/init.h>,<linux/module.h>这两个头文件是模块必须包含的。
module_init用来指定初始化函数,在模块加载的时候会运行,module_exit指定去除模块时要运行的函数。
__init : 当内核把驱动初始化完后, 释放此函数的代码指令空间,此函数只跑一次。
__exit : 指定此函数只在驱动卸载时使用, 用完后释放。
#define __init __section(.init.text)
#define __exit __section(.exit.text)
printk和printf用法一致,这里不能使用prinf,但内核提供了printk打印函数,printk是由分级别的:
#define KERN_EMERG "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
默认级别为4 KERN_WARNING。
查看当前内核的输出级别 cat /proc/sys/kernel/printk
7 4 1 7
7:console_loglevel
4:default_message_loglevel
1:minimum_console_loglevel
7:default_console_loglevel
当printk函数使用的级别小于当前console_loglevel级别时, 则可以输出, 否则不输出
修改级别输出 echo 7 > /proc/sys/kernel/printk
MODULE_LICENSE 指定所支持的协议,必须要有这个!常用的有"GPL",“Dual BSD/GPL”, "GPL v2"等。
MODULE_AUTHOR 作者
MODULE_DESCRIPTION 描述
MODULE_VERSION 版本
一个简单的内核模块就写好了,接下来要进行编译了。
内核模块有两种加载机制,一种是静态加载,一种是动态加载。
静态加载就是把模块编进内核, 在内核启动时加载,动态加载则是把模块编为ko, 在内核启动后,需要用时加载。
静态加载使用obj-y,动态加载使用obj-m。只要在其目录下的Makefile文件下加入即可。如:
obj-m += test.o
如果当前目录没有Makefile文件,创建即可,然后在上级Makefile中添加当前的Makefile的目录。
编译完成将生成test.ko,通过insmod 即可将模块加载入内核中:
$ insmod test.ko
插入后可以在/sys/module/目录下找到test。
使用dmesg或者cat /proc/kmsg可以看到插入时的打印。
去除模块用rmmod,不需要加.ko
$ rmmod test
查看内核当前有哪些模块用lsmod
$ lsmod