Passing Arguments to Linux Device Driver
模块参数宏
module_param()
module_param_array()
module_param_cd()
在此之前,我们需要确定变量的权限,下面是几种权限:
S_IWUSR
S_IRUSR
S_IXUSR
S_IRGRP
S_IWGRP
S_IXGRP
module_param()
这个宏用来初始化参数,这个函数需要三个参数,变量名,变量类型,权限。宏需要放在函数外部。使用时需要 linux/moduleparam.h
头文件:
module_param(name, type, perm);
module_param
会在 /sys/module/
下面创建子目录,比如:
module_param(valueETX, int, SIWUSR | SIRUSR);
将会创建:
/sys/module/hello_world_module/parameters/valueETX
模块参数支持很多类型:
bool
,布尔型,True/Falseinvbool
,反布尔型,False 表示 True,True 表示 Falsecharp
,字符指针型,会为用户提供的字串分配空间- int
- long
- short
- uint
- ulong
- ushort
module_param_array()
将数组做为参数给到设备驱动,声明这个参数:
module_param_array(name, type, num, perm);
其中:
name
,是数组名type
,是数组元素类型num
,整型数,或不指定perm
,权限值
module_param_cb()
这个宏用来注册回调。一旦参数改变,会调用这个回调函数。比如,我们首先创建下面的参数:
module_param(valueETX, int, S_IWUSR | S_IRUSR);
可以通过下面的命令修改这个参数:
sudo su
echo 1 > /sys/module/hello_world_module/parameters/valueETX
这个行为将会更新 valueETX
的值,通过使用 module_param_cb
宏,可以创建一个通知,首先,我们需要首先注册句柄函数到文件操作结构体:
struct kernel_param_ops {
int (*set) (const char *var, const struct kernel_param *kp);
int (*get) (char *buffer, const struct kernel_param *kp);
void (*free) (void *arg);
}
在下面的例子中,介绍了如何使用这个宏来注册参数修改回调函数。
编程示例
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
int valueETX, arr_valueETX[4];
char *nameETX;
int cb_valueETX=0;
module_param(valueETX, int, S_IRUSR | S_IWUSR);
module_param(nameETX, charp, S_IRUSR | S_IWUSR);
module_param_array(arr_valueETX, 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) {
printk(KERN_INFO "Call back function called...\n");
printk(KERN_INFO "New value of cb_valueETX = %d\n", cb_valueETX);
return 0;
}
return -1;
}
const struct kernel_param_ops my_param_ops = {
.set = ¬ify_param,
.get = ¶m_get_int,
};
module_param_cb(cb_valueETX, &my_param_ops, &cb_valueETX, S_IRUGO | S_IWUSR);
static int __init hello_init(void)
{
int i;
printk(KERN_INFO "valueETX = %d\n", valueETX);
printk(KERN_INFO "cb_valueETX = %d\n", cb_valueETX);
printk(KERN_INFO "nameETX = %s\n", nameETX);
printk(KERN_CONT "arr_valueETX: ");
for (i = 0; i < sizeof(arr_valueETX)/sizeof(int); i++)
printk(KERN_CONT "%d ", arr_valueETX[i]);
printk(KERN_CONT "\n");
printk(KERN_INFO "%s success\n", __FUNCTION__);
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_INFO "%s success\n", __FUNCTION__);
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Me");
MODULE_DESCRIPTION("A parameter driver");
MODULE_VERSION("1.0");
编译
在 ubuntu
环境中使用编写下面的 Makefile
文件:
obj-m += hello_world.o
KER_DIR =/lib/modules/$(shell uname -r)/build
all:
make -C $(KER_DIR) M=$(shell pwd) modules
clean:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
执行如下命令编译生成模块:
make
载入模块
sudo insmod hello_world.ko valueETX=14 nameETX="testString" arr_valueETX=100,102,104,106
通过 dmesg
检验参数
$ dmesg | tail -n 5
[5015630.457650] valueETX = 14
[5015630.457652] cb_valueETX = 0
[5015630.457653] nameETX = testString
[5015630.457653] arr_valueETX: 100 102 104 106
[5015630.457656] hello_init success
使用下面命令中的一条修改模块变量值:
sudo sh -c "echo 13 > /sys/module/hello_world_module/parameters/cb_valueETX"
sudo su
echo 13 > /sys/module/hello_world_module/parameters/cb_valueETX
$ dmesg | tail -n 2
[5015706.580696] Call back function called...
[5015706.580697] New value of cb_valueETX = 13
卸载驱动
执行如下命令来卸载驱动:
sudo rmmod hello_world
$ dmesg | tail -n 1
[5015828.286013] hello_exit success
标签:传参,int,cb,param,module,valueETX,hello
From: https://www.cnblogs.com/arvin-blog/p/18021945