以Helloworld这个简单的程序的演示,达到对linux内核模块编程的编译,加载和卸载这个过程有初步认识目的。
hellomod.c源文件
--------------------------------------------------------
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile文件
----------------------------
#如果已定义KERNELRELEASE,则说明是从内核构造系统调用的。
#因此可以利用其内建语句。
ifneq ($(KERNELRELEASE),)
obj-m := hellomod.o
#否则,是直接从命令开始调用的,
#这时要调用内核构造系统。
else
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *.cmd *.ko *.mod
注:
1. Makefile文件的文件名中M一定要大写。这是因为编译的时候首先看环境变量KERNELRELEASE是否定义,如果没定义则调用Linux内核编译build脚本。该脚本会首先编译内核,其间会创建环境变量KERNELRELEASE,接着编译当前工作目录下的hello模块,此时会第二遍读取Makefile,再次判断环境变量KERNELRELEASE是否定义,已经定义的情况下开始编译hello模块。
2. Makefile文件中的命令行,以Tab键开头(不能是空格),例如make,clean。依赖条件顶格,例如default,clean。
3. KDIR:这是正在运行的操作系统内核编译目录,也就是编译模块需要的环境。
4. M:指定源文件的位置。
将hellomod.c和Makefile文件放到同一个文件夹下面(例如test)。在终端进入到test目录下,使用make命令对其进行编译:
[root@zhangli test]# make
make -C /lib/modules/2.6.38.6-26.rc1.fc15.i686.PAE/build M=/home/zhangli/test modules
make[1]: 进入目录“/usr/src/kernels/2.6.38.6-26.rc1.fc15.i686.PAE”
CC [M] /home/zhangli/test/hellomod.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/zhangli/test/hellomod.mod.o
LD [M] /home/zhangli/test/hellomod.ko
make[1]: 离开目录“/usr/src/kernels/2.6.38.6-26.rc1.fc15.i686.PAE”
[root@zhangli test]# insmod ./hellomod.ko
[root@zhangli test]# rmmod hellomod
hellomod.c源文件
--------------------------------------------------------
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile文件
----------------------------
#如果已定义KERNELRELEASE,则说明是从内核构造系统调用的。
#因此可以利用其内建语句。
ifneq ($(KERNELRELEASE),)
obj-m := hellomod.o
#否则,是直接从命令开始调用的,
#这时要调用内核构造系统。
else
KDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
endif
clean:
rm -rf *.o *.cmd *.ko *.mod
注:
1. Makefile文件的文件名中M一定要大写。这是因为编译的时候首先看环境变量KERNELRELEASE是否定义,如果没定义则调用Linux内核编译build脚本。该脚本会首先编译内核,其间会创建环境变量KERNELRELEASE,接着编译当前工作目录下的hello模块,此时会第二遍读取Makefile,再次判断环境变量KERNELRELEASE是否定义,已经定义的情况下开始编译hello模块。
2. Makefile文件中的命令行,以Tab键开头(不能是空格),例如make,clean。依赖条件顶格,例如default,clean。
3. KDIR:这是正在运行的操作系统内核编译目录,也就是编译模块需要的环境。
4. M:指定源文件的位置。
将hellomod.c和Makefile文件放到同一个文件夹下面(例如test)。在终端进入到test目录下,使用make命令对其进行编译:
[root@zhangli test]# make
make -C /lib/modules/2.6.38.6-26.rc1.fc15.i686.PAE/build M=/home/zhangli/test modules
make[1]: 进入目录“/usr/src/kernels/2.6.38.6-26.rc1.fc15.i686.PAE”
CC [M] /home/zhangli/test/hellomod.o
Building modules, stage 2.
MODPOST 1 modules
CC /home/zhangli/test/hellomod.mod.o
LD [M] /home/zhangli/test/hellomod.ko
make[1]: 离开目录“/usr/src/kernels/2.6.38.6-26.rc1.fc15.i686.PAE”
[root@zhangli test]# insmod ./hellomod.ko
[root@zhangli test]# rmmod hellomod
这里实验是用的虚拟机,在仿真器中运行insmod和rmmod,是不会在屏幕上看到任何输出的。实际上它可能输出到系统日志文件中的,例如/var/log/message,打开message,定位到最后,就会看到输出的消息。如下图: