驱动参数实验:编写支持加载时传入参数的驱动

实验简介

在本实验中,我们将学习如何编写一个Linux内核驱动模块,该模块支持在加载时传入参数。例如,使用insmod my_drv.ko debug_level=1命令加载驱动时,可以传入debug_level参数。

驱动参数的基本概念

Linux内核模块允许在加载时通过命令行传递参数。这些参数可以在模块代码中定义,并在模块初始化时使用。参数的类型可以是整数、字符串、数组等。

用户空间 insmod my_drv.ko param1=value1 param2=value2 内核空间 模块参数解析和初始化

常用的模块参数宏

描述 示例
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)");

实验步骤

  1. 定义模块参数:使用module_param宏定义参数。
  2. 处理参数:在模块初始化函数中,使用传入的参数值。
  3. 编译模块:使用Makefile编译模块。
  4. 加载模块:使用insmod命令加载模块并传入参数。
  5. 验证参数:检查参数是否正确传递和处理。

示例代码

以下是一个简单的驱动模块示例,支持传入debug_leveldevice_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文件权限规则。

注意:参数权限决定了是否可以通过/sys/module/<module_name>/parameters/下的文件在运行时修改参数值。

总结

通过本实验,我们学习了如何为Linux内核驱动模块添加参数支持。这允许用户在加载模块时灵活配置模块行为,提高了模块的可用性和可配置性。