linux内核模块的编译
1.准备内核模块源码
首先编写一个简单linux内核模块文件。假设我们有一个源文件mymod.c
。源码如下:
#include<linux/module.h>/*引入与模块相关的宏*/
#include<linux/init.h> /*引入module_init() module_exit()函数*/
#include<linux/moduleparam.h>/*引入module_param()*/
static int ntest=10;
module_param(ntest,int,S_IRUGO);
static int __init test_init(void)
{
int i;
for(i=0; i < ntest; i++)
{
printk(KERN_ALERT "Hello,How are you.%d\n",i);
}
return 0;
}
static void __exit test_exit(void)
{
printk(KERN_ALERT "I come from yuer's module,I have been unlad.\n");
}
module_init(test_init);
module_exit(test_exit);
MODULE_AUTHOR("wyy");
MODULE_LICENSE("GPL");
module_param(ntest,int,S_IRUGO);
是导出我们的符号变量。在加载这个模块的时候可以修改这个变量的值。test_init()函数将在模块被加载的时候运行,通过输出的结果可以看到我们的模块是否加载成功。
2.编写Makefile文件
ubuntu下模块编译Makefile文件
obj-m:=modules.o # modules.o修改为test.o则要对应修改modules-objs为test-objs
modules-objs:=mymod.o #生成这个模块名所需要的目标文件
#NAME:=`uname –r`
#KDIR:=/lib/modules/$(NAME)/build
KDIR:=/lib/modules/`uname –r`/build
PWD:=$(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o .cmd *.ko *.mod.c .tmp_versions *.mod.o *.symvers *.order *Module.markers
嵌入式系统模块编译Makefile文件
obj-m:=modules.o #要生成的模块名
modules-objs:=mymod.o #生成这个模块名所需要的目标文件
KDIR:=/home/wyy/Develop/linux/linux-socfpga #linux源码根目录
PWD:=$(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
clean:
rm -rf *.o .cmd *.ko *.mod.c .tmp_versions *.mod.o *.symvers *.order *Module.markers
现在说明一下Makefile,Makefile首字母是大写的而不是小写的makefile
obj-m:要生成的模块名称,模块的格式为obj-m:=<模块名>.o,假设模块名为module.o
module-objs:模块module需要的目标文件module-objs中的module对应obj-m要生成的模块名称,格式要求<模块名>-objs:=<目标文件>
切记:模块的名字不能取与目标文件相同的名字。如在这里模块名不能取成mymod;KDIR:这是我们正在运行的操作系统内核编译目录。也就是编译模块需要的环境M=:指定我们源文件的位置,PWD:这是当前工作路径$(shell)是make的一个内置函数。用来执行shell命令。
3.编译模块
现在我们已经准备好了我们所需要的源文件和相应的Makefile。我们现在就可以编译了。在终端进入源文件目录输入make运行结果:
4.加载/卸载模块
加载模块
终端输入:sudo insmod modules.ko
加载模块
终端输入:dmesg | tail -12
查看内核输出信息
卸载模块
终端输入:sudo rmmod modules
卸载模块
终端输入:dmesg | tail -3
查看内核输出信息
5.加载模块时传递参数
终端输入:sudo insmod modules.ko ntest=4
终端输入:dmesg | tail -6
查看内核输出信息
可以看到模块在加载的时候初始化函数中的循环只执行了4次。
怎么知道一个模块可以设置那些变量呢?
终端输入ls /sys/module/<modules_name>/parameters/
来查看,这里的<modules_name>
是modules
如果我们的模块加载成功了。最后我们还可以通过modinfo来查看我们的模块信息。如下在终端输入:sudo modinfo modules.ko
显示结果:
总结
模块定义的一些宏在 include\linux\module.h
例如:在写到MODULE_AUTHOR(”wyy”)的时候,你应该想到还有MODULE_DESCRIPTION(模块用途的简单描述);
MODULE_VERSION(模块的版本字符串);
MODULE_ALIAS(模块的别名);
…
在写到module_param(nbr,int,S_IRUGO);的时候,你应该想到还有
EXPORT_SYMBOL(name);可以导出模块的函数,这也是模块编写的最终目的。
在用到insmod和modinfo的时候。你应该想到还有depmod分析可加载模块的依赖性,并生成modules.dep文件和映射文件modprobe,Linux内核添加删除模块