Linux内核开发:内核模块参数 您所在的位置:网站首页 8301模块参数设置 Linux内核开发:内核模块参数

Linux内核开发:内核模块参数

#Linux内核开发:内核模块参数| 来源: 网络整理| 查看: 265

目录

使用参数加载模块

module_param宏

读取和更改参数值

验证参数值

声明模块参数数组

有关模块参数的一些说明

 

在本文中,我们将向模块添加参数。使用参数,您可以在加载模块时访问模块全局变量,并在运行时已加载模块时访问模块全局变量。

 

使用参数加载模块

使用insmod命令加载模块时,可以提供参数作为key = value对,例如:

# insmod ./mymod.ko irq=20 name=mydev debug=1 address=0x1000,0x2000,0x3000

参数可以是数字,字符串或(数字或字符串的)数组

要在模块中声明一个简单参数,请声明一个全局变量并使用module_param宏,例如:

#include #include #include #include static int irq=10; module_param(irq,int,0660); static int debug=0; module_param(debug,int,0660); static char *devname = "simpdev"; module_param(devname,charp,0660); static int simple_init(void) { printk(KERN_WARNING "hello... irq=%d name=%s debug=%d\n",irq,devname,debug); return 0; } static void simple_cleanup(void) { printk(KERN_WARNING "bye... irq=%d name=%s debug=%d\n",irq,devname,debug); } module_init(simple_init); module_exit(simple_cleanup);

现在,您可以使用irq,debug和devname参数编译和加载模块:

# insmod ./simple.ko irq=44 devname=simpdev debug=0

全局变量将在使用use dmesg的init函数查看输出之前进行初始化:

# dmesg ... [ 144.526050] hello... irq=44 name=simpdev debug=0

 

module_param宏

宏原型是

module_param(name, type, perm);

名称–已经定义的变量的名称

type –参数类型(int,long,charp等)

权限– / sys / module / / parameters / 的权限(对于没有这样的模块参数值文件,则为0)

 

读取和更改参数值

/ sys / module / / parameters中的文件用于在加载模块时读取/写入参数值。例如,如果我们加载了一个带有debug = 0的模块,并且想要在不重新加载模块的情况下打开调试消息,则可以使用以下文件:

# echo "1">/sys/module/simple/parameters/debug

您可以在卸载模块时看到调试变量已更改

# rmmod simple # dmesg ... [ 362.125050] bye... irq=44 name=simpdev debug=0

 

验证参数值

使用/ sys中的文件,如果有权限,我们可以设置所需的任何值。例如,如果irq只能在1到32的范围内,则无法验证它,因为用户可以直接访问该变量。为了解决这个问题,我们可以实现一个用于设置获取参数值的接口– kernel_param_ops

struct kernel_param_ops { /* How the ops should behave */ unsigned int flags; /* Returns 0, or -errno. arg is in kp->arg. */ int (*set)(const char *val, const struct kernel_param *kp); /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ int (*get)(char *buffer, const struct kernel_param *kp); /* Optional function to free kp->arg when module unloaded. */ void (*free)(void *arg); };

要实现接口,我们需要定义一个变量,实现set / get方法并使用module_param_cb注册它:

static int my_set(const char *val, const struct kernel_param *kp) { int n = 0, ret; ret = kstrtoint(val, 10, &n); if (ret != 0 || n < 1 || n > 32) return -EINVAL; return param_set_int(val, kp); } static const struct kernel_param_ops param_ops = { .set = my_set, .get = param_get_int, }; static int num; module_param_cb(simpcb, ¶m_ops, &num, 0664);

实际的参数值保存在num中,set函数将用户输入作为字符串并将其转换为int,然后我们检查该值是否正确(1-32)并使用内核提供的param_set_int函数进行设置。要返回参数值,我们使用提供的param_get_int函数

如果尝试使用错误的值加载模块,或者尝试使用/ sys文件设置错误的值,则会出现错误:

$ sudo insmod ./simp.ko irq=9 devname=mydev debug=0 simpcb=200 insmod: ERROR: could not insert module ./simp.ko: Invalid parameters # echo "70">/sys/module/simp/parameters/simpcb bash: echo: write error: Invalid argument

我们还可以为get定义一个自定义函数,但在此示例中它不是必需的。如果希望使用字符串提供参数值但另存为数字,这将很有用

例如,如果我们希望中断模式的参数为水平,边沿,轮询中的一个,但我们想将其保存为数字(1 –水平,2边沿,3轮询),则将定义set函数以从将字符串转换为int并将get函数从int转换为字符串

例如:

enum irq_type { IRQ_TYPE_LEVEL, IRQ_TYPE_EDGE, IRQ_TYPE_POLLING }; static int irq_type = IRQ_TYPE_LEVEL; // default static int irqtype_op_write_handler(const char *val, const struct kernel_param *kp) { char valcp[16]; char *s; strncpy(valcp, val, 16); valcp[15] = '\0'; s = strstrip(valcp); if (strcmp(s, "level") == 0) irq_type = IRQ_TYPE_LEVEL; else if (strcmp(s, "edge") == 0) irq_type = IRQ_TYPE_EDGE; else if (strcmp(s, "polling") == 0) irq_type = IRQ_TYPE_POLLING; else return -EINVAL; return 0; } static int irqtype_op_read_handler(char *buffer, const struct kernel_param *kp) { switch (irq_type) { case IRQ_TYPE_LEVEL: strcpy(buffer, "Level"); break; case IRQ_TYPE_EDGE: strcpy(buffer, "Edge"); break; case IRQ_TYPE_POLLING: strcpy(buffer, "Polling"); break; default: strcpy(buffer, "error"); break; } return strlen(buffer); } static const struct kernel_param_ops irqtype_op_ops = { .set = irqtype_op_write_handler, .get = irqtype_op_read_handler }; module_param_cb(irqtype, &irqtype_op_ops, NULL, 0660);

要加载内核模块或更改参数值,请使用字符串:

# sudo insmod ./simp.ko irq=9 devname=mydev debug=0 simpcb=20 irqtype=edge # cat /sys/module/simp/parameters/irqtype Edge

 

声明模块参数数组

您可以使用module_param_array将参数声明为数字或字符串数​​组。例如:

static int addr[SIZE]; static int count; module_param_array(addr, int, &count, 0660);

加载模块时,请使用逗号分隔的列表来提供值:

# insmod ./simp.ko addr=0x1000,0x2000,0x3000

count是一个输出参数,并使用用户提供的元素数进行更新(在此示例中为3)

 

有关模块参数的一些说明 如果使用modprobe加载模块,则可以在/etc/modprobe.conf(或其他文件-取决于您的发行版)中设置参数。如果使用内核(静态)编译模块,则可以在启动时使用内核命令行提供参数。还有更多功能–查看源代码(moduleparam.h)

源代码:https://github.com/dev-area/module-params

或者:https://github.com/Rtoax/test/tree/master/linux/module/module-params

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有