Linux2.6下开发简单的可加载内核模块

Linux下开发简单的可加载内核模块(2.6内核)

 
1.       模块代码结构
 
头文件
模块宏声明
初始化函数
退出函数
入口出口函数设置
 
最简单的hello.c源文件
//头文件
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
 
//模块宏声明
MODULE_LICENSE( "GPL" );
MODULE_DESCRIPTION( "Fortune Cookie Kernel Module" );
MODULE_AUTHOR( "M. Tim Jones" );
 
//初始化函数
static int __init mod_init_func(void)
{
       printk(KERN_EMERG "Hello, world/n");
 
       return 0;
}
 
//模块推出函数
static void __exit mod_exit_func(void)
{
       printk(KERN_EMERG "Goodbye, world/n");
}
//入口出口函数设置
module_init(mod_init_func);
module_exit(mod_exit_func);
 
 
2.       模块代码编译
 
2.6内核环境中编译模块代码和2.4有很大区别,2.6中,内核已经存在一个写好的Makefile模板,在目录/lib/modules/$(shell uname -r)/build/下。因此我们编写的Makefile中只需要指定需要编译的模块代码的名称以及当前目录即可。
 
Makefile模板
 
SRC = /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
obj-m := hello.o
 
default:
       $(MAKE) -C $( SRC) M=$(PWD) modules
 
clean:
       rm –f *.o *.ko .*.cmd .*.flags *.mod.c
 
还有一个完美点的例子,优点是它可以区分出来自己是在内核源码树里面被编译的还是在源码树之外被编译的:
 
#如果已定义KERNELRELEASE,则说明是从内核构造系统调用的,因此可利用其内建语句。
ifneq($(KERNELRELEASE),)
       obj-m :=hello.o
#否则,是直接从命令行调用的,这时要调用内核构造系统
else
       KERNELDIR ?= /lib/modules/$(shell uname -r)/build
       PWD := $(shell pwd)
default:
       $(MAKE) –C $(KERNELDIR) M=$(PWD) modules
endif
 
注意,Makefile的文件名必须是头字母大写的Makefile
 
我们在hello.c当前目录下运行make,编译成功后会生成以下文件:
hello.ko 
hello.mod.c 
hello.mod.o 
hello.o
Module.symvers
 
其中, hello.ko就是我们需要的模块执行文件,它是一个特殊的ELF文件。
我们运行objdump –t hello.ko,可以查看其symbol table.
 
3.       模块管理命令
 
Linux提供了命令来管理模块
(1)    insmod 安装模块
(2)    rmmod 卸载模块
(3)    lsmod  查看已加载模块
 
我们首先使用insmod加载模块:
insmod hello.ko
这是可以看到输出 Hello, world
如果在控制台中看不到,我们可以使用命令dmesg来查看系统输出
然后再卸载模块
rmmod hello
这是可以看到输出 Goodbye, world.

你可能感兴趣的:(Linux2.6下开发简单的可加载内核模块)