目录
1、模块加载(入口)函数
模块加载函数,用于在模块加载时执行一些初始化操作,比如注册设备、初始化数据结构等。
static int __init xxx_init(void)
{
printk("-----------[%s]-------------\n", __FUNCTION__);
return 0;
}
使用命令 insmod xxx.ko 可以加载模块
使用命令 lsmod 可以查看加载模块的信息
不可重复加载模块
2、模块卸载(出口)函数
模块卸载函数,用于在模块卸载时执行一些清理工作,比如释放资源、注销设备等。
static void __exit xxx_exit(void)
{
printk("-----------[%s]-------------\n", __FUNCTION__);
}
使用命令 rmmod xxx.ko 可以加载模块,例如
此时 lsmod 中就没有模块信息
不可重复卸载模块
3、模块加载声明
module_init
宏就是用来告诉内核在加载该模块时应该调用哪个函数来执行初始化操作。
module_init(xxx_init);
4、模块卸载声明
module_exit
宏用于指定模块卸载时应该调用的函数。
module_exit(xxx_exit);
5、 模块认证
MODULE_LICENSE
宏用于在 Linux 内核模块中指定模块的许可证信息。这个宏的作用是告诉内核模块的使用者,该模块的代码所遵循的许可证类型。在 Linux 内核模块中,模块的许可证信息是很重要的,因为它决定了模块的代码在法律上的使用方式。
MODULE_LICENSE("license_type");
6、模块编译
编写 Makefile 文件示例如下
#指定内核源码路径
KERNEL_DIR = /home/tx/samba_shared/mp157/kernel/linux-5.4.31
#指定当前模块所在位置
CURRENT_DIR = `pwd`
#编译内核
all:
make -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
#删除内核
clean:
make -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
#将模块拷贝到开发板的系统中
install:
cp *.ko /opt/myrootfs/drv_modules
#指定要编译的具体模块
obj-m=hello.o
make -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules 详解
- make: 这是 GNU Make 工具的命令。它用于执行 Makefile 中定义的规则,以便自动化代码的编译和构建过程。
- -C $(KERNEL_DIR): 这个选项告诉 Make 去指定的目录中执行构建操作。KERNEL_DIR 是一个变量,代表 Linux 内核源代码的目录。在这个命令中,Make 将会进入 KERNEL_DIR 所指定的目录中执行编译操作。
- M=$(CURRENT_DIR): 这个选项告诉 Make 模块的源代码所在的目录。CURRENT_DIR 是一个变量,代表当前模块源代码的目录。通过这个选项,Make 知道在哪里可以找到要编译的模块源代码。
- modules: 这是 Makefile 中定义的一个目标。它告诉 Make 编译目标为模块类型的代码,即 Linux 内核模块。
总体来说,这个命令告诉 make 进入内核源代码目录 (KERNEL_DIR
),并使用当前模块源代码目录 (CURRENT_DIR
) 中的代码来构建模块。最终,在shell 终端执行 make 会编译并生成模块对象文件,以便后续加载到内核中使用。
7、 模块加载时传参
module_param
是一个 Linux 内核编程中常用的宏,用于在模块加载时接收参数。通过使用module_param
宏,你可以在加载模块时传递参数给模块,从而改变模块的行为或配置。
module_param(name, type, permissions);
使用示例如下
int age;
char *name;
static int __init hello_init(void)
{
printk("-----------[%s]-------------\n", __FUNCTION__);
printk("name = %s, age = %d\n", name, age);
return 0;
}
module_param(name, charp, 0644);
module_param(age, int, 0644);
此时在 insmod hello.ko 时就可以给 age 和 name 传递参数
可以在 /sys/module/hello/parameters 目录下查看模块参数信息
模块中的参数会在该目录下创建同名的文件,文件中会保存参数的值
8、综合代码示例
//头文件
#include <linux/init.h>
#include <linux/module.h>
int age;
char *name;
//模块加载(入口)函数
static int __init hello_init(void)
{
printk("-----------[%s]-------------\n", __FUNCTION__);
printk("name = %s, age = %d\n", name, age);
return 0;
}
//模块卸载(出口)函数
static void __exit hello_exit(void)
{
printk("-----------[%s]-------------\n", __FUNCTION__);
}
//声明参数
module_param(name, charp, 0644);
module_param(age, int, 0644);
//声明与认证
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");