#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
static int __init mod_init(void)
{
return 0;
}
static void __exit mod_exit(void)
{
printk("cleanup module\n");
}
module_init(mod_init);
module_exit(mod_exit);
一、头文件
- linux/init.h
在init.h头文件中包含了模块的初始化的宏定义 以及一些其他函数的初始化函数
参考:http://blog.csdn.net/kokodudu/article/details/17361161 - linux/kernel.h
kernel.h中包含了内核打印函数 printk函数 等
参考:http://blog.csdn.net/kokodudu/article/details/17371103 - linux/module.h
参考:http://blog.csdn.net/kokodudu/article/details/17358001
二、函数
- static int __init mod_init(void)
这个函数是函数的入口,也就是说内核在加载这个模块的时候会去调用这个函数。 - static void __exit mod_exit(void)
模块被卸载的时候会调用这个函数 - module_init(mod_init);
这个函数的作用是为内核模块指定一个入口,在加载内核模块的时候就会调用这个函数的参数对应的函数,也就说第一个函数并不是默认的函数入口,它是我们自己定义的函数的入口,使用 module_init() 这个函数来指定我们自定义的内核模块加载入口 - module_exit
作用同上,指定内核模块被卸载的时候调用的函数
三、关键字
- static
在内核中的函数非常多,我们为我们自己的函数命名很可能就会和Linux其他牛人的重名,这就会导致在编译的时候会报重定义,所以我们就在这加上 staitc 关键字来修饰,来避免和其他函数重名的情况,从ANSI C的角度出发,这就会导致这个函数不能被外部文件调用,而我们知道,Linux 其实是一个宏内核,也就是说内核中的所有函数之间都是直接调用的,而我们这里这样定义会导致其他文件不能调用这个函数,那怎么办呢?其实不用担心,因为版本比较新一点的编译器已经为我们解决了这个问题,编译器在编译的时候就会帮我们处理这个问题,使得被 static 关键字修饰的函数能被外部文件调用。 - __init
这个修饰词是两个下划线加上init( _ _ init),Linux效率非常高,其中一个原因就来源于它对内存的管理可以说是十分"吝啬",static int __init mod_init(void)这个函数其实只是在加载的时候需要,在加载完成之后就没有必要让它继续占用内存了,我们可以使用 __init来修饰它,使得它在完成自己的使命后不再占用内存
四、Makefile
obj-m := mymod.o #module name
mymod-objs:= mymodtest.o
KDIR :=/lib/modules/`uname -r`/build
PWD:=$(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o *.order *.symvers .cmd *.ko *.mod.c .tmp_versions
Makefile说明。
请记住是大写的Makefile而不是小写的makefile;
obj-m
:指定模块, 格式: obj-m := <模块名>.o
mymod-objs
:声称模块(modules)需要的目标文件, 格式: <模块名>-objs := <目标文件>
! 切 ! 记 !
:模块的名字不能取与目标文件相同的名字。如在这里模块名不能取成 mymod;
KDIR
:这是我们正在运行的操作系统内核编译目录。也就是编译模块需要的环境M=
: 指定源文件的位置PWD
:这是当前工作路径,$(shell )
是make的一个内置函数。用来执行shell命令。