linux驱动模块参数传递的三种玩法!

linux驱动模块参数传递的三种玩法! Mary 2023-08-22 13:38:20 633

一、简介

在嵌入式linux应用开发中,可以给main()函数传递参数,这样应用程序就能知道最初的控制参数是什么,当然也可以选择不向应用程序传递参数。在驱动开发中,会使用到insmod命令来加载一个驱动模块,这时候我们也可以使用insmod命令向驱动模块传递参数。

使用模块的参数传递机制,对调试系统非常方便!

二、参数传递方式

参数传递分为两种:

  • 内置模块参数传递:即将模块编译构建进内核镜像。
  • 外置模块参数传递:使用insmod等命令装在的内核模块。

对于内置模块参数传递,一般在bootloader中可向内置的模块传递参数,例如可以在bootargs中设置模块名.参数名=值的形式给该内置的模块传递参数;对于外置模块,在装载内核模块时,我们可以向模块传递参数,形式为:

insmode(或 modprobe)模块名 参数名=参数值

如果不传递参数,参数将使用模块内定义的缺省值。

三、技术点

1、变量权限

向驱动模块传递参数,必须事先在驱动源码中声明某一个变量可作为模块参数传递,并且指定变量的权限,常见的权限参数如下:

易百纳社区

上述宏定义中,S_I是公共的写法,R = read,W = write ,X = execute , USR = user,GPR = group。

当然,也可以这样看:可以将数字最后三位转化为二进制:xxx xxx xxx,高位往低位依次看,第一位为 1 表示文件所有者可读,第二位为 1 表示文件所有者可写,第三位为 1 表示文件所有者可执行;接下来三位表示文件所有者同组成员的权限;再下来三位为不同组用户权限。

使用'|'(或操作),可以一次设置多个权限。

了解了一个变量有哪些常见的权限可供设置,接下来看看如何将一个变量声明为可传递参数的变量。

2、传递普通的参数

传递普通的参数(例如 boolcharint),使用下列宏定义:

module_param(name,type,perm);
  • name:要传递进去参数的名称。
  • type:要传递进去参数的类型。
  • perm:要传递进去参数的读写权限。

module_param()宏在/sys/module下创建子目录。上述代码,将在/sys/module/中可查看对应的参数:

3、传递数组

传递数组参数使用下列的宏定义:

module_param_array(name,type,nump,perm)
  • name:要传递进去参数的名称。
  • type:要传递进去参数的类型。
  • nump:实际传入进去参数的个数。
  • perm:要传递进去参数的读写权限。

4、参数改变时回调

我们已经知道,可以向/sys/module/下的参数名称写入参数,这意味将改变参数的值,如果使用module_param()module_param_array(),则无法获知参数的值是否改变,如果我们想要让系统获知参数的改变,并根据参数改变进一步执行处理,则需要使用module_param_cb()注册参数值改变时的处理函数。在内核中,module_param_cb()宏用于注册回调,每当参数(形参)发生变化时,将调用此回调函数:

module_param_cb(name, ops, arg, perm) 
  • name:要传递进去参数的名称。
  • ops:该参数的set和get操作。
  • arg:传递给ops中回到函数的参数。
  • perm:要传递进去参数的读写权限。

四、代码实验

例如下列代码:

/***********************************************************************************
 * @Copyright: ©Iriczhao Co., Ltd. 2021-2029. All rights reserved.
 * @File: dt_param_trans_demo.c
 * @Descripttion:linux kernel module parameter passing experiment       
 * @version:1.0 
 * @Author: iriczhao
 * @Date: 2023-08-7 15:50:06
 * @LastEditors: iriczhao
 * ***********************************************************************************/
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/module.h>
#include<linux/moduleparam.h>
 
int value, arr_value[4];
char *name;
int cb_value = 0;

//声明模块参数
module_param(value, int, S_IRUSR|S_IWUSR);                      //integer 类型
module_param(name, charp, S_IRUSR|S_IWUSR);                     //String  类型
module_param_array(arr_value, int, NULL, S_IRUSR|S_IWUSR);      //整型数组
 
/*----------------------Module_param_cb()--------------------------------*/
int notify_param(const char *val, const struct kernel_param *kp)
{
    int res = param_set_int(val, kp); // Use helper for write variable
    
    if(res == 0) {
        printk(KERN_INFO "Call back function called...\n");
        printk(KERN_INFO "New value of cb_value = %d\n", cb_value);
        return 0;
    }
    
    return -1;
}
 
const struct kernel_param_ops my_param_ops = 
{
    .set = notify_param, 
    .get = param_get_int, 
};
 
module_param_cb(cb_value, &my_param_ops, &cb_value, S_IRUGO|S_IWUSR );

static int __init dt_param_trans_demo_init(void)
{
    int i;
    //打印出模块参数
    printk(KERN_INFO "Value = %d  \n", value);
    printk(KERN_INFO "cb_value = %d  \n", cb_value);
    printk(KERN_INFO "Name = %s \n", name);
    for (i = 0; i < (sizeof arr_value / sizeof (int)); i++) {
        printk(KERN_INFO "Arr_value[%d] = %d\n", i, arr_value[i]);
    }
    printk(KERN_INFO "Kernel Module Inserted Successfully...\n");
    return 0;
}


static void __exit dt_param_trans_demo_exit(void)
{
    printk(KERN_INFO "Kernel Module Removed Successfully...\n");
}
 
module_init(dt_param_trans_demo_init);
module_exit(dt_param_trans_demo_exit);
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("iriczhao");
MODULE_DESCRIPTION("linux kernel module parameter passing experiment");
MODULE_VERSION("1.0");

将上述代码以模块方式构建,然后将生成的dt_param_trans_demo.ko模块载入内核,在加载该模块时,传入valuenamearr_value的参数值,在程序中将会打印出输出的参数值:

易百纳社区

从上述输出的结果中,cb_value的参数值为0(默认参数值),然后我们通过向/sys/module/dt_param_trans_demo/parameters/cb_value文件写入参数值,这时候将会触发该参数改变时绑定的回调函数,并打印出修改过后的参数值:

易百纳社区

在载入一个模块后,我们可以在/sys/module/模块名/parameters/目录下查看该模块包含导出了哪些动态参数(参数以文件名称表示),以及对应参数的权限(文件的权限对应参数的权限),例如本例中,将在/sys/module/dt_param_trans_demo/parameters/目录下查看:

易百纳社区

五、总结

1、模块在载入的时候可以传递参数给模块,前提是在模块中提前声明需要传递的参数。

2、当在系统启动后,在/sys/module/模块名/parameters/目录中可以查看对应模块下导出了哪些参数。也可以通过该目录下的文件向对应的参数传递信新的参数值。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
Mary
红包 点赞 1 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
Mary
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区