天天看点

Linux内核模块简介

Linux内核模块简介

要想使编写的驱动程序生效,就需要把写好的代码编入到内核中。那怎么把自己写的代码放入内核进行编译呢?总共有两种方法:
1)把所有需要的功能编入内核即可实现。但是这么做会产生两个问题:
第一个问题是如果所编写的代码中有错误,需要调试,那么每一次都需要重新编译整个内核,这会非常消耗时间。这么说有的小
伙伴就会问了,这又能消耗多长时间呢?以笔者亲身经历的一个嵌入式项目来看,重编依次内核大约2小时左右。假设你调试代
码需要3次才能调试通过(实际工程中三次调试好一个功能都属于大神级别的人物了,除非你调的功能非常简单),那光是编译
内核就需要6个小时,再加上包括版本升级之类的操作再占去2个小时,那就是相当于一天的工作投入,如果你那功能需要调试7-
8次,那可能两三天的工作量就投进去然后还未必能把活干明白。所以说实际工程中要是敢这么干,别的不说,你的领导肯定要
找你谈话了。。。
第二个问题是,如果随便什么功能都往内核中编译,那么这个内核会越来越大,这也是我们不想看到的。
2)第二种方法,也是实际开发中最长使用的一种方法。它依赖Linux提供的一种叫做“模块”的机制,模块有几个特点,第一个
特点是:模块本身不被编译进内核,从而控制了内核的大小。第二个特点是:当需要一个模块时,可以动态加载,模块一旦被
加载,他就和内核中的其他部分完全一样了。

接下来写一个最基础样例看一看:
           

helloko.c

#include <linux/init.h>
	#include <linux/module.h>
	
	static __init int hello_init(void)
	{
		printk(KERN_EMERG  "Hello KO enter!\n");
		return 0;
	}
	
	static void __exit hello_exit(void)
	{
		printk(KERN_EMERG  "Hello KO exit!\n");
	}
	
	module_init(hello_init);
	module_exit(hello_exit);
	MODULE_LICENSE("DUAL BSD/GPL");
在这里插入代码片
           

Makefile

KVERS = $(shell uname -r)
	
	#Kernel modules
	obj-m += helloko.o
	
	CURDIR=$(shell pwd)
	
	
	all: 
		make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
	
	clean:
		make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

           

先解释下helloko.c文件,hello_init是内核模块加载函数,一般用__init声明,通过module_init调用;

hello_exit是内核模块卸载函数,一般用__exit声明,通过module_exit调用。

MODULE_LICENSE(“GPL”)是模块许可声明,是固定内容且是必写的。

以上三块内容构成最基本的内核模块,这三块都是必写的。

printk函数是内核空间的输出函数,由于内核空间不是用户空间,不能使用printf,故只能使用printk。

printk有7个输出数据等级,我这里使用的KERN_EMERG是第0级,也是优先级最高的输出级别,代

表“紧急事件消息,系统崩溃之前提示,表示系统不可用”,小伙伴们可以根据实际需要选用合适的输

出级别。

再来看看Makefile文件

事先声明一下,和.c一样,我写的Makefile也是最简形式,实际工程中Makefile的编写要复杂的多。

make -C /lib/modules/ ( K V E R S ) / b u i l d 指 明 跳 转 到 源 码 目 录 下 读 取 那 里 的 M a k e f i l e 。 M = (KVERS)/build指明跳转到源码目录下读取那里的Makefile。 M= (KVERS)/build指明跳转到源码目录下读取那里的Makefile。M=(CURDIR)表明执行完源码的Makefile后返回到当前目录继续读入。

至于$(shell xxx)代表了在Makefile中执行shell命令。

当前目录下文件结构是这样的:

Linux内核模块简介

再介绍几个命令:

lsmod命令:获取系统中加载了的所有模块以及模块间的依赖关系,例如

Linux内核模块简介

insmod命令:加载模块命令。

rmmod命令:卸载模块命令。

下面开始编译.ko文件

1、执行make命令,得到以下文件,其中helloko.ko文件就是我们需要加载的.ko文件。

Linux内核模块简介

2、执行insmod命令,注意.ko文件的出现方式,另外由于我的虚拟机没有使用root用户,所以需要输入sudo

如果使用root用户的话,就不必sudo了。

Linux内核模块简介

3、执行lsmod看看helloko.ko是否已经加载成功,从图片来看果真加载成功了。

Linux内核模块简介

4、既然模块加载成功了,那么有些小伙伴就会你问了,打印呢?怎么屏幕没有输出打印信息呢?其实内核打印信息

和用户空间打印信息不同,它可以不输出到屏幕上,要看内核打印信息,还需要执行dmesg命令。红框中就是我添加的打印。

Linux内核模块简介

5、执行rmmod命令,注意和insmod命令的helloko.ko参数形式做对比

Linux内核模块简介

6、执行lsmod看看是否卸载干净,看图可知,没有helloko模块,可知模块已经卸载干净了。

Linux内核模块简介

7、再次执行dmesg,看是否有模块卸载的打印信息。由图可知,是有打印信息的。

Linux内核模块简介

以上就是加载与卸载一个最基础模块的步骤,如有错误,欢迎批评指正。