Keep looking Donot settle
分类: 嵌入式
2014-12-03 17:49:54
前面讲了内核模块怎么安装和卸载,那么现在就正式讲解一下内核模块怎么编写。
以一个在内核中打印出”hello world”到终端的例子讲解。
1、 首先要写模块加载时的入口函数和模块卸载时的入口函数
static int hello_init()
{
printk(“<0>hello world\n”);
return 0;
}
static void hello_exit()
{
printk(“<0>exit\n”);
}
module_init(hello_init);
module_exit(hello_exit);
这几段代码就是一个模块函数代码了,其中有几个需要注意:
a) static是为了防止函数命名污染。
b) 在内核中的打印函数是printk,其中<0>表示该信息的等级,数字越小,级别越高。
c) 用module_init和module_exit宏来指定入口函数。
当在命令行安装该模块时,会自动调用hello_init这个函数,当卸载该函数时,对自动调用hello_exit函数。
2、 模块可选信息
模块有一些用来表示相关信息的宏:
MODULE_LICENSE 用来告诉内核遵循什么协议 GPL GPLv2等
MODULE_AUTHOR 作者
MODULE_DESCRIPTION 描述
MODULE_VERSION 版本
MODULE_ALIAS 别名
例如:
MODULE_LICENSE("GPL");
MODULE_AUTHOR("yangboyuan");
MODULE_DESCRIPTION("KernelLink Module");
MODULE_ALIAS("asimplest module");
3、 Makefile文件的编写
大家都知道make命令,所以Makefile文件的作用在这里就没必要做过多介绍,我们先看看内核模块的Makefile怎么写的:
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
KDIR := /lib/modules/2.6.35.6-45.fc14.i686/build
all:
make-C $(KDIR) M=$(PWD) modules
clean:
rm-f *.ko *.o *.mod.o *.mod.c *.symvers
endif
其中:
a) KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量。
ifneq($(KERNELRELEASE),) 判断该变量是否为空。
在第一次读取执行此Makefile时,KERNELRELEASE没有被定义,
所以make将读取执行else之后的内容。
b) KDIR := /lib/modules/2.6.35.6-45.fc14.i686/build 是给KDIR这个变量赋值,值为当前linux运行的内核源码。红色标记的只是我的Linux下的,可以直接
KDIR := /lib/modules/ $(shell uname -r) /build 这样写。
c) 当make的目标为all时,-C $(KDIR) 指明跳转到内核源码目录下读取那里的Makefile;M=$(PWD)表明然后返回到当前目录继续读入、执行当前的Makefile。当从内核源码目录返回时,KERNELRELEASE已被被定义,kbuild也被启动去解析kbuild语法的语句,make将继续读取else之前的内容。
d) 我们可以把上述的Makefile文件作为一个模板,只需要改动obj-m := hello.o这条语句就可以了:obj-m=XXX.o。
4、Makefile文件编写好了之后,在内核模块代码的当前目录下敲命令:”make”
会生成一系列文件,而在2.6内核里面,我们只需要将hello.ko文件安装好就可以了, 怎么安装看“内核模块的加载与卸载”那一章节。
from: http://blog.csdn.net/yby19870627/article/details/7360259