内核参数更改信号

问题描述 投票:0回答:2

我想在内核(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 = &param_get_ushort, // .. and standard getter
};

unsigned short param = 0xff;
module_param_cb(param,    /*filename*/
    &my_param_ops_ushort, /*operations*/
    &param,               /* 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)

就像魅力一样!

c linux-kernel kernel kernel-module
2个回答
7
投票

创建内核模块参数的通用方法是使用宏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 = &param_get_ushort, // .. and standard getter }; // Usage unsigned short param = 0xff; module_param_cb(param, /*filename*/ &my_param_ops_ushort, /*operations*/ &param, /* pointer to variable, contained parameter's value */ S_IRUGO | S_IWUSR /*permissions on file*/ );


出于安全原因,让非特权用户可写模块参数通常并不好。以及创建模块参数的内核宏,检查这一点。这就是为什么你的模块参数的定义中有神秘错误。请注意,在上面的示例中,使用
S_IWUSR

而不是

S_IWUGO
    


1
投票

有几种方法可以检测此变量的更改。您可以使用内核线程作为一种机制。

更好的方法可能是使用 sysfs 或 procfs 条目。它们具有在读取和写入时调用的读/写处理程序。

请参阅此处的

sysfs教程


    

© www.soinside.com 2019 - 2024. All rights reserved.