我想在内核(3.x)模块内使用参数:
static char param = 0xff;
module_param(param, ushort, S_IRUGO | S_IWUGO);
MODULE_PARM_DESC(param, "a parameter");
是否有可能检测到该参数的变化?有没有可以用来调用服务例程的信号?
这里是完整的代码示例:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
static int param = 1;
module_param(param, int, S_IRUGO|S_IWUSR);
static int __init mod_init(void){
printk(KERN_INFO "param %d\n", param);
return 0;
}
static void __exit mod_exit(void){
printk(KERN_INFO "Goodbye!\n");
}
module_init(mod_init);
module_exit(mod_exit);
现在您可以在
/sys/module/<modulename>/parameters
下找到参数,您可以像这样更改参数:
sudo echo 2 > /sys/module/ebb/parameters/param
我希望收到有关该更改的通知。
关于@Tsyvarev的下一步
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
// int (*set)(const char *val, const struct kernel_param *kp);
// int (*get)(char *buffer, const struct kernel_param *kp);
int my_param_set_ushort(const char *val, const struct kernel_param *kp)
{
unsigned short* pvalue = kp->arg; // Pointer to actual parameter variable.
int res = param_set_ushort(val, kp); // Use helper for write variable
printk(KERN_INFO "setter talks\n");
if( res==0 )
{
// Here you may execute additional actions when you write parameter.
printk(KERN_INFO "set param %d\n", *pvalue);
}
return res;
}
const struct kernel_param_ops my_param_ops_ushort =
{
.set = &my_param_set_ushort, // Use our setter ...
.get = ¶m_get_ushort, // .. and standard getter
};
unsigned short param = 0xff;
module_param_cb(param, /*filename*/
&my_param_ops_ushort, /*operations*/
¶m, /* pointer to variable, contained parameter's value */
S_IRUGO | S_IWUSR /*permissions on file*/
);
static int __init mod_init(void){
printk(KERN_INFO "param %d\n", param);
return 0;
}
static void __exit mod_exit(void){
printk(KERN_INFO "Goodbye! (%d)\n",param);
}
module_init(mod_init);
module_exit(mod_exit);
作为 root,我发出以下命令:
# insmod par.ko
# echo 146 > /sys/module/par/parameters/param
# rmmod par
内核日志/var/log/kernel.log说:
Jan 23 14:27:37 alex-XMG kernel: [ 8332.492912] param 255
Jan 23 14:27:39 alex-XMG kernel: [ 8334.520044] setter talks
Jan 23 14:27:39 alex-XMG kernel: [ 8334.520052] set param 146
Jan 23 14:27:40 alex-XMG kernel: [ 8335.804338] Goodbye! (146)
就像魅力一样!
创建内核模块参数的通用方法是使用宏module_param_cb:
/**
* module_param_cb - general callback for a module/cmdline parameter
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define module_param_cb(name, ops, arg, perm)
参数
ops
是指向结构struct kernel_param_ops
的指针,其中包含给定参数的操作。写入和读取参数时调用的函数遵循此结构中的定义:
int (*set)(const char *val, const struct kernel_param *kp);
int (*get)(char *buffer, const struct kernel_param *kp);
这里
char*
参数是一个以NULL结尾的字符串,它写入/读取sysfs文件,表示给定参数。 kp
是指向参数描述符的指针,其中最感兴趣的字段是.arg
:它是宏module_param_cb
调用的第三个参数。使用这个字段,可以实现模块参数的per-type的setter和getter,即模块有5个int
参数,不需要为每个参数编写setter和getter。
此外,标准参数类型的 getter 和 setter 已经实现,并且在调用
module_param
宏时实际使用它们。因此,如果您想为参数的设置器添加一些功能,您可以重用现有的助手:
int my_param_set_ushort(const char *val, const struct kernel_param *kp)
{
unsigned short* pvalue = kp->arg; // Pointer to actual parameter variable.
int res = param_set_ushort(val, kp); // Use helper for write variable
if(!res)
{
// Here you may execute additional actions when you write parameter.
printk(KERN_INFO "set param %d\n", *pvalue);
}
return res;
}
const struct kernel_param_ops my_param_ops_ushort =
{
.set = &my_param_set_ushort, // Use our setter ...
.get = ¶m_get_ushort, // .. and standard getter
};
// Usage
unsigned short param = 0xff;
module_param_cb(param, /*filename*/
&my_param_ops_ushort, /*operations*/
¶m, /* pointer to variable, contained parameter's value */
S_IRUGO | S_IWUSR /*permissions on file*/
);
出于安全原因,让非特权用户可写模块参数通常并不好。以及创建模块参数的内核宏,检查这一点。这就是为什么你的模块参数的定义中有神秘错误。请注意,在上面的示例中,使用
S_IWUSR
而不是
S_IWUGO
。