module_param
该宏定义在include/linux/moduleparam.h中
#define ___module_cat(a,b) __mod_ ## a ## b #define __module_cat(a,b) ___module_cat(a,b) #define __MODULE_INFO(tag, name, info) \ static const char __module_cat(name,__LINE__)[] \ __used \ __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info #define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type)
/* This is the fundamental function for registering boot/module parameters. perm sets the visibility in sysfs: 000 means it\'s not there, read bits mean it\'s readable, write bits mean it\'s writable. */ #define __module_param_call(prefix, name, set, get, arg, perm) \ /* Default value instead of permissions? */ \ static int __param_perm_check_##name __attribute__((unused)) = \ BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ + BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN); \ static const char __param_str_##name[] = prefix #name; \ static struct kernel_param __moduleparam_const __param_##name \ __used \ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ = { __param_str_##name, perm, set, get, { arg } } #define module_param_call(name, set, get, arg, perm) \ __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm) /* Helper functions: type is byte, short, ushort, int, uint, long, ulong, charp, bool or invbool, or XXX if you define param_get_XXX, param_set_XXX and param_check_XXX. */ #define module_param_named(name, value, type, perm) \ param_check_##type(name, &(value)); \ module_param_call(name, param_set_##type, param_get_##type, &value, perm); \ __MODULE_PARM_TYPE(name, #type) #define module_param(name, type, perm) \ module_param_named(name, name, type, perm)
下面以驱动模块中的用例展开宏,
static int tiger=1; module_param(tiger,int,S_IRUGO)
1.第一步展开
#define module_param(name, type, perm) \ module_param_named(name, name, type, perm)
展开结果为
module_param_named(tiger,tiger,int,S_IRUGO)
2.第二步展开,展开为三项
/* Helper functions: type is byte, short, ushort, int, uint, long, ulong, charp, bool or invbool, or XXX if you define param_get_XXX, param_set_XXX and param_check_XXX. */ #define module_param_named(name, value, type, perm) \ param_check_##type(name, &(value)); \ module_param_call(name, param_set_##type, param_get_##type, &value, perm); \ __MODULE_PARM_TYPE(name, #type)
2.1 param_check_##type(name, &(value));
展开结果为,又是一个宏定义
__param_check(tiger, &(tiger), int)
#define __param_check(name, p, type) \ static inline type *__check_##name(void) { return(p); }
上面的宏再展开为一个内联函数,返回某类型的指针
static inline int*__check_tiger(void) { return(&(tiger));
2.2 module_param_call(name, param_set_##type, param_get_##type, &value, perm);
这也是一个宏
#define MODULE_PARAM_PREFIX /* empty */
#define module_param_call(name, set, get, arg, perm) \ __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm)
展开为
__module_param_call(MODULE_PARAM_PREFIX,tiger, param_set_int, param_get_int, &tiger, S_IRUGO)
#define __module_param_call(prefix, name, set, get, arg, perm) \ /* Default value instead of permissions? */ \ static int __param_perm_check_##name __attribute__((unused)) = \ BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ + BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN); \ static const char __param_str_##name[] = prefix #name; \ static struct kernel_param __moduleparam_const __param_##name \ __used \ __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ = { __param_str_##name, perm, set, get, { arg } }
上面的宏又展开为3项
2.2.1
static int __param_perm_check_tiger __attribute__((unused)) = BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) + BUILD_BUG_ON_ZERO(sizeof(""prefix) > MAX_PARAM_PREFIX_LEN);
2.2.2
static const char __param_str_tiger[] = "tiger";
2.2.3
static struct kernel_param __param_tiger __used __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) = { __param_str_tiger, S_IRUGO, param_set_int, param_get_int, {&tiger} }
2.3 __MODULE_PARM_TYPE(name, #type)
#define __MODULE_PARM_TYPE(name, _type) \ __MODULE_INFO(parmtype, name##type, #name ":" _type)
该宏展开如下
__MODULE_INFO(parmtype, tigertype, "tiger" ":" "int")
#define ___module_cat(a,b) __mod_ ## a ## b #define __module_cat(a,b) ___module_cat(a,b) #define __MODULE_INFO(tag, name, info) \ static const char __module_cat(name,__LINE__)[] __used \
__attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
最终展开为
static const char __mod_tigertype__LINE__[] __attribute__((section(".modinfo"),unused)) = "parmtype=tiger:int"
还有一个重要的宏,定义了get/set参数的函数
#define STANDARD_PARAM_DEF(name, type, format, tmptype, strtolfn) \ int param_set_##name(const char *val, struct kernel_param *kp) \ { \ tmptype l; \ int ret; \ \ if (!val) return -EINVAL; \ ret = strtolfn(val, 0, &l); \ if (ret == -EINVAL || ((type)l != l)) \ return -EINVAL; \ *((type *)kp->arg) = l; \ return 0; \ } \ int param_get_##name(char *buffer, struct kernel_param *kp) \ { \ return sprintf(buffer, format, *((type *)kp->arg)); \ }
以STANDARD_PARAM_DEF(int, int, “%i”, long, strict_strtol);为例展开如下:
int param_set_int(const char *val, struct kernel_param *kp) { long l; int ret; if (!val) return -EINVAL; ret = strict_strtol(val, 0, &l); if (ret == -EINVAL || ((long)l != l)) return -EINVAL; *((long *)kp->arg) = l; return 0; } int param_get_int(char *buffer, struct kernel_param *kp) { \ return sprintf(buffer, "%i", *((long *)kp->arg)); }