在本实验中,我们将学习如何编写一个Linux内核驱动模块,该模块支持在加载时传入参数。例如,使用insmod my_drv.ko debug_level=1
命令加载驱动时,可以传入debug_level
参数。
Linux内核模块允许在加载时通过命令行传递参数。这些参数可以在模块代码中定义,并在模块初始化时使用。参数的类型可以是整数、字符串、数组等。
宏 | 描述 | 示例 |
---|---|---|
module_param |
定义单个参数(整数、字符串、布尔值等) | module_param(debug_level, int, 0644); |
module_param_array |
定义数组参数 | module_param_array(ids, int, &num_ids, 0644); |
module_param_string |
定义字符串参数 | module_param_string(name, name_buf, sizeof(name_buf), 0644); |
MODULE_PARM_DESC |
为参数添加描述 | MODULE_PARM_DESC(debug_level, "Debug level (0-3)"); |
module_param
宏定义参数。insmod
命令加载模块并传入参数。以下是一个简单的驱动模块示例,支持传入debug_level
和device_name
参数。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int debug_level = 0;
static char device_name[64] = "default_device";
module_param(debug_level, int, 0644);
MODULE_PARM_DESC(debug_level, "Debug level (0-3)");
module_param_string(device_name, device_name, sizeof(device_name), 0644);
MODULE_PARM_DESC(device_name, "Device name string");
static int __init my_drv_init(void)
{
printk(KERN_INFO "My driver initialized with debug_level=%d and device_name=%s\n",
debug_level, device_name);
return 0;
}
static void __exit my_drv_exit(void)
{
printk(KERN_INFO "My driver exited\n");
}
module_init(my_drv_init);
module_exit(my_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple driver with module parameters");
使用以下Makefile编译模块:
obj-m += my_drv.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
编译完成后,加载模块并传入参数:
sudo insmod my_drv.ko debug_level=2 device_name=my_device
使用dmesg
命令查看内核日志,确认参数是否正确传递:
dmesg | tail -n 2
输出应类似:
[ 1234.567890] My driver initialized with debug_level=2 and device_name=my_device
在module_param
宏中,第三个参数是参数的权限。例如,0644
表示所有者可读写,组和其他用户只读。权限值遵循Unix文件权限规则。
0644
:所有者可读写,组和其他只读0666
:所有用户可读写0444
:所有用户只读/sys/module/<module_name>/parameters/
下的文件在运行时修改参数值。
通过本实验,我们学习了如何为Linux内核驱动模块添加参数支持。这允许用户在加载模块时灵活配置模块行为,提高了模块的可用性和可配置性。