linux驱动模块参数传递方式

一、简介
在嵌入式linux应用开发中,可以给main()函数传递参数,这样应用程序就能知道最初的控制参数是什么,当然也可以选择不向应用程序传递参数。在驱动开发中,会使用到insmod命令来加载一个驱动模块,这时候我们也可以使用insmod命令向驱动模块传递参数。
使用模块的参数传递机制,对调试系统非常方便!
二、参数传递方式
参数传递分为两种:
内置模块参数传递:即将模块编译构建进内核镜像。
外置模块参数传递:使用insmod等命令装在的内核模块。
对于内置模块参数传递,一般在bootloader中可向内置的模块传递参数,例如可以在bootargs中设置模块名.参数名=值的形式给该内置的模块传递参数;对于外置模块,在装载内核模块时,我们可以向模块传递参数,形式为:
insmode(或 modprobe)模块名 参数名=参数值  
如果不传递参数,参数将使用模块内定义的缺省值。
三、技术点
1、变量权限
向驱动模块传递参数,必须事先在驱动源码中声明某一个变量可作为模块参数传递,并且指定变量的权限,常见的权限参数如下:
宏定义 权限解释
#defines_irusr 00400 文件所有者可读
#defines_iwusr 00200 文件所有者可写
#defines_ixusr 00100 文件所有者可执行
#defines_irgrp 00040 与文件所有者同组的用户可读
#defines_iwgrp 00020  
#defines_ixgrp 00010  
#defines_iroth 00004 与文件所有者不同组的用户可读
#defines_iwoth 00002  
#defines_ixoth 00001
上述宏定义中,s_i是公共的写法,r = read,w = write ,x = execute , usr = user,gpr = group。
当然,也可以这样看:可以将数字最后三位转化为二进制:xxx xxx xxx,高位往低位依次看,第一位为 1 表示文件所有者可读,第二位为 1 表示文件所有者可写,第三位为 1 表示文件所有者可执行;接下来三位表示文件所有者同组成员的权限;再下来三位为不同组用户权限。
使用'|'(或操作),可以一次设置多个权限。
了解了一个变量有哪些常见的权限可供设置,接下来看看如何将一个变量声明为可传递参数的变量。
2、传递普通的参数
传递普通的参数(例如 bool、char、int),使用下列宏定义:
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 1506 * @lasteditors: iriczhao * ***********************************************************************************/#include#include#include#include 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...);        printk(kern_info new value of cb_value = %d, 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  , value);    printk(kern_info cb_value = %d  , cb_value);    printk(kern_info name = %s , name);    for (i = 0; i < (sizeof arr_value / sizeof (int)); i++) {        printk(kern_info arr_value[%d] = %d, i, arr_value[i]);    }    printk(kern_info kernel module inserted successfully...);    return 0;}static void __exit dt_param_trans_demo_exit(void){    printk(kern_info kernel module removed successfully...);} 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模块载入内核,在加载该模块时,传入value、name、arr_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/目录中可以查看对应模块下导出了哪些参数。也可以通过该目录下的文件向对应的参数传递信新的参数值。


关于AMP连接器在汽车市场中的应用
商汤论文精选:计算机视觉和深度学习技术最新突破
Linux嵌入式操作系统在嵌入式系统中的应用才刚刚开始
人工智能算法的演进升级需要高质量数据作为支撑
智能控制型电饭锅电路图
linux驱动模块参数传递方式
全功能光纤USB3.1 Gen2线缆的特点和应用
新能源利用如何“泛能化”?
联发科超越高通成全球手机芯片领域的王者
人脸识别助力反欺诈
浅谈JAE MX80系列车用级小型防水连接器
中科曙光入选智能制造标杆企业名单!
赛普拉斯推出可替代用户名、PIN和密码的指纹读取器
移远通信发布2019年年度报告,实现营业收入41.3亿元
单相电度表的反转
oc有垃圾回收机制吗?arc和垃圾回收机制的区别?
石英晶体振荡器的基本原理
喜讯!巨蟹数科荣获国家级“高新技术企业”认定!
PLC远程监控系统给汽车装备的制造带来了哪些优势
日本推出AIST人形机器人意在纾解老龄少子化所造成的劳动人口短缺问题