该宏定义在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));	
}

  

版权声明:本文为yangjiguang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/yangjiguang/p/8290518.html