文章目录
1 module_param_cb
1.1 待解析内容:
// block/genhd.c
module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops,
&disk_events_dfl_poll_msecs, 0644);
1.2 涉及到的相关定义:
// block/genhd.c
static const struct kernel_param_ops disk_events_dfl_poll_msecs_param_ops = {
.set = disk_events_set_dfl_poll_msecs,
.get = param_get_ulong,
};
/* disable in-kernel polling by default */
static unsigned long disk_events_dfl_poll_msecs;
#define MODULE_PARAM_PREFIX "block."
1.3 涉及到的通用定义
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) \
__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0)
/* This is the fundamental function for registering boot/module
parameters. */
#define __module_param_call(prefix, name, ops, arg, perm, level, flags) \
/* Default value instead of permissions? */ \
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, THIS_MODULE, ops, \
VERIFY_OCTAL_PERMISSIONS(perm), level, flags, { arg } }
struct kernel_param
// include/linux/moduleparam.h
struct kernel_param {
const char *name;
struct module *mod;
const struct kernel_param_ops *ops;
const u16 perm;
s8 level;
u8 flags;
union {
void *arg;
const struct kparam_string *str;
const struct kparam_array *arr;
};
};
struct kernel_param_ops
// include/linux/moduleparam.h
struct kernel_param_ops {
/* How the ops should behave */
unsigned int flags;
/* Returns 0, or -errno. arg is in kp->arg. */
int (*set)(const char *val, const struct kernel_param *kp);
/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
int (*get)(char *buffer, const struct kernel_param *kp);
/* Optional function to free kp->arg when module unloaded. */
void (*free)(void *arg);
};
kernel_param_ops 中 get、set函数的定义
// kernel/params.c
#define STANDARD_PARAM_DEF(name, type, format, strtolfn) \
int param_set_##name(const char *val, const struct kernel_param *kp) \
{ \
return strtolfn(val, 0, (type *)kp->arg); \
} \
int param_get_##name(char *buffer, const struct kernel_param *kp) \
{ \
return scnprintf(buffer, PAGE_SIZE, format "\n", \
*((type *)kp->arg)); \
} \
const struct kernel_param_ops param_ops_##name = { \
.set = param_set_##name, \
.get = param_get_##name, \
}; \
EXPORT_SYMBOL(param_set_##name); \
EXPORT_SYMBOL(param_get_##name); \
EXPORT_SYMBOL(param_ops_##name)
STANDARD_PARAM_DEF(byte, unsigned char, "%hhu", kstrtou8);
STANDARD_PARAM_DEF(short, short, "%hi", kstrtos16);
STANDARD_PARAM_DEF(ushort, unsigned short, "%hu", kstrtou16);
STANDARD_PARAM_DEF(int, int, "%i", kstrtoint);
STANDARD_PARAM_DEF(uint, unsigned int, "%u", kstrtouint);
STANDARD_PARAM_DEF(long, long, "%li", kstrtol);
STANDARD_PARAM_DEF(ulong, unsigned long, "%lu", kstrtoul);
STANDARD_PARAM_DEF(ullong, unsigned long long, "%llu", kstrtoull);
1.4 基于1.1的展开流程
1、
module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops,
&disk_events_dfl_poll_msecs, 0644);
2、
__module_param_call(MODULE_PARAM_PREFIX, events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops, &disk_events_dfl_poll_msecs, 0644, -1, 0)
3、
static const char __param_str_events_dfl_poll_msecs[] = "block.events_dfl_poll_msecs"; \
static struct kernel_param __moduleparam_const __param_events_dfl_poll_msecs \
__used \
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \
= { __param_str_events_dfl_poll_msecs, THIS_MODULE, &disk_events_dfl_poll_msecs_param_ops, \
VERIFY_OCTAL_PERMISSIONS(0644), -1, 0, { &disk_events_dfl_poll_msecs } }
2 module_param
module_param
#define module_param(name, type, perm) \
module_param_named(name, name, type, perm)
module_param_named
#define module_param_named(name, value, type, perm) \
param_check_##type(name, &(value)); \
module_param_cb(name, ¶m_ops_##type, &value, perm); \
__MODULE_PARM_TYPE(name, #type)
param_check_( )
// include/linux/moduleparam.h
#define param_check_byte(name, p) __param_check(name, p, unsigned char)
#define param_check_short(name, p) __param_check(name, p, short)
#define param_check_ushort(name, p) __param_check(name, p, unsigned short)
#define param_check_int(name, p) __param_check(name, p, int)
#define param_check_uint(name, p) __param_check(name, p, unsigned int)
#define param_check_long(name, p) __param_check(name, p, long)
#define param_check_ulong(name, p) __param_check(name, p, unsigned long)
...
__param_check
// include/linux/moduleparam.h
// 注意name就是内核传参的参数名
#define __param_check(name, p, type) \
static inline type __always_unused *__check_##name(void) { return(p); }
__MODULE_PARM_TYPE
// include/linux/moduleparam.h
#define __MODULE_PARM_TYPE(name, _type) \
__MODULE_INFO(parmtype, name##type, #name ":" _type)
__MODULE_INFO (不深究此宏)
// include/linux/moduleparam.h
#ifdef MODULE
#define __MODULE_INFO(tag, name, info) \
static const char __UNIQUE_ID(name)[] \
__used __attribute__((section(".modinfo"), unused, aligned(1))) \
= __stringify(tag) "=" info
#else /* !MODULE */
/* This struct is here for syntactic coherency, it is not used */
#define __MODULE_INFO(tag, name, info) \
struct __UNIQUE_ID(name) {}
#endif
3、推荐(详细的参数解析流程)
linux kernel的cmdline参数解析原理分析
或者
linux kernel的cmdline参数解析原理分析
他们是一样的内容