linux内核模块的编译

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内核添加删除模块

猜你喜欢

转载自blog.csdn.net/wyy626562203/article/details/79537381