写点什么

Linux 设备驱动系列(三)——参数传递

  • 2024-04-24
    浙江
  • 本文字数:1706 字

    阅读完需:约 6 分钟

Linux设备驱动系列(三)——参数传递

关注微信公众号:Linux 内核拾遗

文章来源:https://mp.weixin.qq.com/s/ach-ex8gqs7l_q6mQn6rwg


在 C 语言应用程序中,可以通过在 main 函数定义中添加 argc 和 argv 参数来获取用户的输入。类似的,Linux 设备驱动程序同样可以传递参数。本文将介绍 Linux 设备驱动程序中参数定义以及使用方法。

1 模块参数宏

Linux 头文件"linux/module.h"提供了多个宏来声明内核模块的参数及其读写权限。


  • S_IWUSR、S_IRUSR、S_IXUSR;

  • S_IRGRP、S_IWGRP、S_IXGRP。


其中,R/W/X 分别表示读、写和执行权限,USR/GRP 分别表示用户和用户组。


允许通过"|"运算符来同时设置多个权限。


下面将简要介绍模块参数宏的使用方法,这些宏都在"linux/moduleparam.h"中定义。

1.1 module_param()

module_param()宏有三个参数:参数名,参数类型,以及参数权限掩码。


module_param(name, type, perm);
复制代码


定义的模块参数可以在"/sys/module//parameters/"下面找到。


// /sys/module/my_driver/parameters/my_parammodule_param(my_param, int, S_IWUSR|S_IRUSR);
复制代码


模块参数类型有以下几种:


  1. 布尔类型:bool,invbool;

  2. 字符指针类型:charp;

  3. 基本整型类型:int,long,short,uint,ulong,ushort。

1.2 module_param_array()

module_param_array()宏用于声明以","分隔的数组类型的参数:


module_param_array(name, type, num, perm);
复制代码

1.3 module_param_cb()

module_param_cb()宏用于注册一个回调函数,当参数取值改变时被调用。最常见的应用场景是在内核模块运行期间动态修改其配置。


如果用 module_param_cb()声明一个具有可写权限的模块参数,当内核模块插入内核后,可以通过网对应的 sysfs 文件写入值来修改模块参数的取值,例如"echo 1 > /sys/module/my_driver/parameters/my_param",那么注册的回调函数将会被调用。


struct kernel_param_ops {  int (*set)(const char *val, const struct kernel_param *kp);  int (*get)(char *buffer, const struct kernel_param *kp);  void (*free)(void *arg);};
module_param_cb(name, ops, param_ptr, perm);
复制代码


module_param_cb()接收一个 struct kernel_param_ops 类型的参数作为模块参数的回调函数。

2 示例:Linux 设备驱动参数传递

下面是一个简单的 Linux 设备驱动参数传递的示例代码,定义了 4 个模块参数:


module_param.c


#include<linux/kernel.h>#include<linux/init.h>#include<linux/module.h>#include<linux/moduleparam.h> int int_param, arr_param[4];char *str_param;int cb_param = 0;
module_param(int_param, int, S_IRUSR|S_IWUSR);module_param(str_param, charp, S_IRUSR|S_IWUSR); module_param_array(arr_param, int, NULL, S_IRUSR|S_IWUSR);
int notify_param(const char *val, const struct kernel_param *kp){ int res = param_set_int(val, kp); if(res == 0) { pr_info("New value of cb_param = %d\n", cb_param); return 0; } return -1;}const struct kernel_param_ops my_param_ops = { .set = &notify_param, .get = &param_get_int,};module_param_cb(cb_param, &my_param_ops, &cb_param, S_IRUGO|S_IWUSR );
static int __init hello_world_init(void){ int i; pr_info("int_param = %d\ncb_param = %d\nstr_param = %s\n", int_param, cb_param, str_param); for (i = 0; i < ARRAY_SIZE(arr_param); i++) pr_info("arr_param[%d] = %d\n", i, arr_param[i]); pr_info("Kernel Module Inserted!\n"); return 0;}
static void __exit hello_world_exit(void){ pr_info("Kernel Module Removed!\n");} module_init(hello_world_init);module_exit(hello_world_exit); MODULE_LICENSE("GPL");MODULE_AUTHOR("feifei <feifei@gmail.com>");MODULE_DESCRIPTION("A simple linux device driver");MODULE_VERSION("1.0");
复制代码


说明:如果不特别注明,示例代码均采用前文的示例 Makefile 文件(修改相应的.o 文件名即可),这里不再重复给出。


最后编译运行,输出如图:



关注微信公众号:Linux 内核拾遗

文章来源:https://mp.weixin.qq.com/s/ach-ex8gqs7l_q6mQn6rwg

发布于: 刚刚阅读数: 6
用户头像

聚沙成塔 2023-01-12 加入

分享Linux内核开发相关的编程语言、开发调试工具链、计算机组成及操作系统内核知识、Linux社区最新资讯等

评论

发布
暂无评论
Linux设备驱动系列(三)——参数传递_linux开发_Linux内核拾遗_InfoQ写作社区