LKM可加载内核模块简单实例编写

1.标准的module代码如下:
helloworld.c

#include <linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
MODULE_LICENSE("GPL");
static int hello_init(void)
{
printk(KERN_WARNING "HELLOWORLD");
return 0;
}

static void hello_exit(void)
{
printk("BYE");
}
module_init(hello_init);
module_exit(hello_exit);

2.标准的Makefile文件如下:

obj-m :=helloworld.o
all:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Makefile文件解释如下:

使用kbuild进行模块编译
obj-m := name.o表示会编译一个模块(-m),生成的name.o文件来自于name.c文件。
uname -r 命令返回的实际就是你现在使用的内核版本,比如说我的系统:
所以-C选项后面完整的路径是:/lib/modules/3.13.0-19-generic/build,但是不建议给出具体的路径,而是用$(shell uname -r)这种可变的路径,这样,当你在低版本内核中编译过,拿到高版本内核中再次编译的时候也能正常通过。

3.编译:
$make
编译结果

4.编译完成之后能够看到模块文件:
$ sudo insmod ./hello.ko #加载

$ sudo rmmod hello #删除

$ sudo rmmod ./hello.ko#删除

5.查看模块是否被加载
$lsmod
模块已加载
Used by :引用次数

6.查看源代码输出信息,即查看相应系统日志
$tail /var/log/kern.log
查看日志信息

7.编写模块声明

#include <linux/module.h> //这个头文件包含了许多符号与函数的定义,这些符号与函数多与加载模块有关
#include <linux/init.h>   //这个头文件包含了你的模块初始化与清除的函数

//另外,如果你的模块需要用到参数传递,那么你可能就要声明moduleparam.h这个头文件了。
//再者,模块里常包含一些描述性声明,如:
MODULE_LICENSE("GPL");      // "GPL" 是指明了 这是GNU General Public License的任意版本
                            // “GPL v2” 是指明 这仅声明为GPL的第二版本
                            // "GPL and addtional"
                            // "Dual BSD/GPL"
                            // "Dual MPL/GPL"
                            // "Proprietary"  私有的
                            // 除非你的模块显式地声明一个开源版本,否则内核会默    认你这是一个私有的模块(Proprietary)。
MODULE_AUTHOR  // 声明作者
MODULE_DESCRIPTION  // 对这个模块作一个简单的描述,这个描述是"human-readable"的
MODULE_VERSIO    // 这个模块的版本
MODULE_ALIAS     // 这个模块的别名
MODULE_DEVICE_TABLE   // 告诉用户空间这个模块支持什么样的设备

//MODULE_声明可以写在模块的任何地方(但必须在函数外面),但是惯例是写在模块最后。

阅读更多
换一批

没有更多推荐了,返回首页