注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

Linux内核模块的参数定义以及定义处理参数的回调函数的宏 module_param module_param_call module_param_cb  

2011-03-23 13:49:54|  分类: linux相关 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
定义一个内核参数比较简单
module_param(参数变量名字,类型,访问权限)
MODULE_PARM_DESC(参数变量名字,“参数说明描述”)

如果需要限制或者检查用户输入的参数的值,比如说限制输入的整型数是 256~512的某个范围等等,输入的一定是某个特定字符串等。那么可以用这个宏。这个支持你传进去一个参数处理的回调函数。
module_param_call    2.6.35 以下
module_param_cb      2.6.38


看内核中的定义
--------------------------
2.6.38里面是 module_param_cb宏

  76/**
  77 * module_param - typesafe helper for a module/cmdline parameter
  78 * @value: the variable to alter, and exposed parameter name.
  79 * @type: the type of the parameter
  80 * @perm: visibility in sysfs.
  81 *
  82 * @value becomes the module parameter, or (prefixed by KBUILD_MODNAME and a
  83 * ".") the kernel commandline parameter.  Note that - is changed to _, so
  84 * the user can use "foo-bar=1" even for variable "foo_bar".
  85 *
  86 * @perm is 0 if the the variable is not to appear in sysfs, or 0444
  87 * for world-readable, 0644 for root-writable, etc.  Note that if it
  88 * is writable, you may need to use kparam_block_sysfs_write() around
  89 * accesses (esp. charp, which can be kfreed when it changes).
  90 *
  91 * The @type is simply pasted to refer to a param_ops_##type and a
  92 * param_check_##type: for convenience many standard types are provided but
  93 * you can create your own by defining those variables.
  94 *
  95 * Standard types are:
  96 *      byte, short, ushort, int, uint, long, ulong
  97 *      charp: a character pointer
  98 *      bool: a bool, values 0/1, y/n, Y/N.
  99 *      invbool: the above, only sense-reversed (N = true).
 100 */
 101#define module_param(name, type, perm)                          \
 102        module_param_named(name, name, type, perm)
 103
 104/**
 105 * module_param_named - typesafe helper for a renamed module/cmdline parameter
 106 * @name: a valid C identifier which is the parameter name.
 107 * @value: the actual lvalue to alter.
 108 * @type: the type of the parameter
 109 * @perm: visibility in sysfs.
 110 *
 111 * Usually it's a good idea to have variable names and user-exposed names the
 112 * same, but that's harder if the variable must be non-static or is inside a
 113 * structure.  This allows exposure under a different name.
 114 */
 115#define module_param_named(name, value, type, perm)                        \
 116        param_check_##type(name, &(value));                                \
 117        module_param_cb(name, &param_ops_##type, &value, perm);            \
 118        __MODULE_PARM_TYPE(name, #type)
 119
 120/**
 121 * module_param_cb - general callback for a module/cmdline parameter
 122 * @name: a valid C identifier which is the parameter name.
 123 * @ops: the set & get operations for this parameter.
 124 * @perm: visibility in sysfs.
 125 *
 126 * The ops can have NULL set or get functions.
 127 */
 128#define module_param_cb(name, ops, arg, perm)                                 \
 129        __module_param_call(MODULE_PARAM_PREFIX,                              \
 130                            name, ops, arg, __same_type((arg), bool *), perm)


------------------------------------------------------------------------------------------
2.6.35里面是 module_param_call宏

  98#define module_param_call(name, set, get, arg, perm)                          \
  99        __module_param_call(MODULE_PARAM_PREFIX,                              \
 100                            name, set, get, arg,                              \
 101                            __same_type(*(arg), bool), perm)
 102
 103/* Helper functions: type is byte, short, ushort, int, uint, long,
 104   ulong, charp, bool or invbool, or XXX if you define param_get_XXX,
 105   param_set_XXX and param_check_XXX. */
 106#define module_param_named(name, value, type, perm)                        \
 107        param_check_##type(name, &(value));                                \
 108        module_param_call(name, param_set_##type, param_get_##type, &value, perm); \
 109        __MODULE_PARM_TYPE(name, #type)
 110
 111#define module_param(name, type, perm)                          \
 112        module_param_named(name, name, type, perm)

-------------------------------------------------------------------------

看几个使用例子


module_param_call(nlm_grace_period, param_set_grace_period, param_get_ulong,
                 &nlm_grace_period, 0644);
                 

----------------------------

static struct kernel_param_ops param_ops_debug_layer = {
        .set = param_set_uint,
        .get = param_get_debug_layer,
};

module_param_cb(debug_layer, &param_ops_debug_layer, &acpi_dbg_layer, 0644);



 103static int param_get_debug_layer(char *buffer, const struct kernel_param *kp)
 104{
 105        int result = 0;
 106        int i;
 107
 108        result = sprintf(buffer, "%-25s\tHex        SET\n", "Description");
 109
 110        for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) {
 111                result += sprintf(buffer + result, "%-25s\t0x%08lX [%c]\n",
 112                                  acpi_debug_layers[i].name,
 113                                  acpi_debug_layers[i].value,
 114                                  (acpi_dbg_layer & acpi_debug_layers[i].value)
 115                                  ? '*' : ' ');
 116        }
 117        result +=
 118            sprintf(buffer + result, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS",
 119                    ACPI_ALL_DRIVERS,
 120                    (acpi_dbg_layer & ACPI_ALL_DRIVERS) ==
 121                    ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS)
 122                    == 0 ? ' ' : '-');
 123        result +=
 124            sprintf(buffer + result,
 125                    "--\ndebug_layer = 0x%08X ( * = enabled)\n",
 126                    acpi_dbg_layer);
 127
 128        return result;
 129}




内核预定义的处理函数,param_set_int 等等
http://lxr.linux.no/#linux+v2.6.38/kernel/params.c

 220/* Lazy bastard, eh? */
 221#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn)       \
 222        int param_set_##name(const char *val, const struct kernel_param *kp) \
 223        {                                                               \
 224                tmptype l;                                              \
 225                int ret;                                                \
 226                                                                        \
 227                ret = strtolfn(val, 0, &l);                             \
 228                if (ret == -EINVAL || ((type)l != l))                   \
 229                        return -EINVAL;                                 \
 230                *((type *)kp->arg) = l;                                 \
 231                return 0;                                               \
 232        }                                                               \
 233        int param_get_##name(char *buffer, const struct kernel_param *kp) \
 234        {                                                               \
 235                return sprintf(buffer, format, *((type *)kp->arg));     \
 236        }                                                               \
 237        struct kernel_param_ops param_ops_##name = {                    \
 238                .set = param_set_##name,                                \
 239                .get = param_get_##name,                                \
 240        };                                                              \
 241        EXPORT_SYMBOL(param_set_##name);                                \
 242        EXPORT_SYMBOL(param_get_##name);                                \
 243        EXPORT_SYMBOL(param_ops_##name)
 244


又有一个例子。

 276static int mmu_audit_set(const char *val, const struct kernel_param *kp)
 277{
 278        int ret;
 279        unsigned long enable;
 280
 281        ret = strict_strtoul(val, 10, &enable);
 282        if (ret < 0)
 283                return -EINVAL;
 284
 285        switch (enable) {
 286        case 0:
 287                mmu_audit_disable();
 288                break;
 289        case 1:
 290                mmu_audit_enable();
 291                break;
 292        default:
 293                return -EINVAL;
 294        }
 295
 296        return 0;
 297}








可以知道我们可以定义一个自己的处理函数,然后可以在自己的函数里面调用param_set_int等函数来获得值,或者自己直接用strtolfn等函数直接解析字符串,自己处理参数的输入设置。我写一个简单的例子,限制整型数输入参数范围为256 到512的。



============================================
static int param_set_int_in_range(const char *val, struct kernel_param *kp)
{
  int hr;

  hr = param_set_int(val, kp);
  if (hr!=0) {
    printk("仅接受整型数值,无效的输入'%s'\n", val);
    return hr;
  }  
 

  if ( *((int *)kp->arg)  < 256 ) {
      printk("%s这个参数的最小值为256,把它设置为256了\n", kp->name);
      *((int *)kp->arg) = 256;
  }
 
  if ( *((int *)kp->arg) > 512 ) {
      printk("%s这个参数的大值为512,把它设置为512了\n", kp->name);
      *((int *)kp->arg) = 512;
  }     

  return 0;
}



//static struct kernel_param_ops param_ops_test = {
//        .set = param_set_int_in_range,
//        .get = param_get_int,
//};
int test_param = 256;  //默认的参数
//module_param_cb(test_param, &param_ops_test, &test_param, 0644);

module_param_call(test_param, param_set_int_in_range,param_get_int, &test_param, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
MODULE_PARM_DESC(test_param,"测试一下限制参数范围玩玩");


-------------------------
modinfo ./jprobe.ko
filename:       ./jprobe.ko
license:        GPL
srcversion:     512C54991CFA1A338DD0F9C
depends:        
vermagic:       2.6.35.8 SMP mod_unload modversions 686
parm:           test_param:测试一下限制参数范围玩玩



sudo insmod  jprobe.ko test_param=123
test_param这个参数的最小值为256,把它设置为256了
cat /sys/module/jprobe/parameters/test_param
256

sudo insmod jprobe.ko  test_param=567
test_param这个参数的大值为512,把它设置为512了
cat /sys/module/jprobe/parameters/test_param
512


直接把参数写到配置文件 /etc/modprobe.conf ,应该也是一样的。
  评论这张
 
阅读(2688)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017