代码编写
第一个.c源文件命名为test.c,其中只有一个函数,在内核中打印一句"hello world!"。
// test.c
// --------------------------------
#include "test.h"
void test(void)
{
printk("hello world!\n");
return;
}
第二个.c源文件命名为main.c,其中包含了模块加载和卸载部分。模块加载和卸载时各有一句打印,同时在模块加载时,调用了第一个源文件中的test()函数。
// main.c
// --------------------------------
#include "test.h"
static int hello_init(void)
{
printk("hello init!\n");
test();
return 0;
}
static void hello_exit(void)
{
printk("hello exit!\n");
return;
}
module_init(hello_init);
module_exit(hello_exit);
编写一个头文件test.h,包括必要的头文件、协议和作者声明、函数声明。
// test.h
// --------------------------------
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("z_mss");
void test(void);
编写Makefile文件,内容如下。
ifneq ($(KERNELRELEASE),)
obj-m := model.o
model-objs := main.o test.o
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
make -C $(KDIR) M=$(PWD) clean
endif
内核模块的Makefile编写方法请参考我的这篇博客,这具体解释一下这个Makefile的特别之处,即如何将多个源文件编译在一起。
obj-m参数指定最后得到的.ko文件来自于model.o文件,即由model.o生成model.ko文件。
model-objs参数指定了model.o的来源,来自于main.o和test.o,而main.o和test.o默认由main.c和test.c分别编译得到。注意,model-objs这个名字是不固定的,假设我们最后将.ko的名字改为命名成model_1.ko,则Makefile就要做出下面的相应修改。
ifneq ($(KERNELRELEASE),)
obj-m := model_1.o
model_1-objs := main.o test.o
编译运行
输入make指令编译一下。
sudo -s指令进入root模式。
insmod指令加载模块,dmesg查看一下内核打印,可以看到成功加载了模块并调用了另一个源文件下的test函数。
rmmod指令移除模块,dmesg查看打印,可以看到成功移除了模块。