linux模块编程测试
趁着今天天气好,进行了一下测试。
我的环境是:BT5R3 内核:3.2.6
第一步:在任意一个目录下新建一个C文件。例如/root/Desktop/KernelModule/hello.c
第二步:编辑C文件,输入一下内容:
#include
#include
static int __init hello_init(void){
printk("Hello World\n");
return 0;
}
static void __exit hello_exit(void)
{
printk("GOODBYE\n");
}
MODULE_AUTHOR("ADAM");
MODULE_DESCRIPTION("GREETINGS");
MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);
第三步:在同一目录下创建一个Makefile文件,无后缀名,输入以下内容:
obj-m :=hello.o
第四步:打开终端,用CD命令进入C文件的目录,例如我的是:
cd /root/Desktop/KernelModule
第五步:输入以 下命令
make -C /usr/src/linux-source-3.2.6/ modules M=$PWD
注意将其中的版本号替换为你的内核的版本号
第六步:此时,应该有诸如下面的提示告诉你模块编译完成:
make: Entering directory `/usr/src/linux-source-3.2.6'
WARNING: Symbol version dump /usr/src/linux-source-3.2.6/Module.symvers
is missing; modules will have no dependencies and modversions.
CC [M] /root/Desktop/kernelModule/hello.o
Building modules, stage 2.
MODPOST 1 modules
CC /root/Desktop/kernelModule/hello.mod.o
LD [M] /root/Desktop/kernelModule/hello.ko
第七步:截止目前你已经编译出了.ko的内核模块文件。下面就要将他加载进内核中。我们使用insmod命令
insmod ./hello.ko
其中的./表示在当前目录下查找
第八步:内核加载的时候执行了我们刚才的hello_init函数,为了查看打印出的内容我们使用dmesg
在终端输入:dmesg |tail
tail表示只查看结尾处的信息
应该能看到HelloWorld
第九步:我们已经将自己的模块加载进入了内核,下一步我们把它移除
在终端输入: rmmod ./hello.ko
同样用 dmesg 可以查看 hello_exit函数打印出的内容BYEBYE
FAQ:
1.编译报错
若出现如下错误,则是由于程序输入所致:
WARNING: Symbol version dump /usr/src/linux-source-3.2.6/Module.symvers
is missing; modules will have no dependencies and modversions.
CC [M] /root/Desktop/kernelModule/hello.o
/root/Desktop/kernelModule/hello.c:5: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘hello_init’
/root/Desktop/kernelModule/hello.c:10: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘hello_exit’
/root/Desktop/kernelModule/hello.c: In function ‘__inittest’:
/root/Desktop/kernelModule/hello.c:19: error: ‘hello_init’ undeclared (first use in this function)
/root/Desktop/kernelModule/hello.c:19: error: (Each undeclared identifier is reported only once
/root/Desktop/kernelModule/hello.c:19: error: for each function it appears in.)
/root/Desktop/kernelModule/hello.c: In function ‘__exittest’:
/root/Desktop/kernelModule/hello.c:20: error: ‘hello_exit’ undeclared (first use in this function)
make[1]: *** [/root/Desktop/kernelModule/hello.o] Error 1
make: *** [_module_/root/Desktop/kernelModule] Error 2
make: Leaving directory `/usr/src/linux-source-3.2.6
注意第四行的_init应为__init,也就是说在init前面应该有两个下划线
2.hello_init和hello_exit函数是否要为静态的
很多其他资料说一定要为静态的,我实际测试结果表明不用加static
3.如何加载模块
insmod ./hello.ko该命令用于加载指定模块进入内核
另外一个常用命令式modprobe
与lsmod的不同之处在于他能自动处理依赖关系,例如模块A依赖模块B,在用modprobe A时,他会先加载B
但是modprobe 的搜索路径限制在modules目录下,不能用modprobe ./hello.ko命令加载当前目录下的模块
而我们写的简单模块并不需要依赖其他模块,因此可以直接用insmod加载
4.如何删除模块
rmmod ./hello.ko
删除模块,此时将执行exit函数