前言
使用过程中有疑问就追了下流程,记录下
基于 3.18 内核
流程
【1】使用方法:
// 第三方驱动中
static struct kernel_param_ops param_ops_hashtbl_sz = {
.set = param_set_hashtbl_sz,
.get = param_get_hashtbl_sz,
};
module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644);
【2】内核声明:
// Moduleparam.h (kernel-3.18\include\linux)
#define module_param_named(name, value, type, perm) \
param_check_##type(name, &(value)); \
module_param_cb(name, ¶m_ops_##type, &value, perm); \
/////////////////////////////////////////////////////////////
#define module_param_cb(name, ops, arg, perm) \
__module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1, 0)
///////////////////////////////////////////////////////////////////////////
#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, ops, VERIFY_OCTAL_PERMISSIONS(perm), \
level, flags, { arg } }
///////////////////////////////////////////////////////////////////////////////
// 对应链接脚本中的段为:
SECTIONS{
RO_DATA(PAGE_SIZE)
///////////////////////////////////////////////////////////////////////////
// Vmlinux.lds.h (kernel-3.18\include\asm-generic)
#define RODATA RO_DATA_SECTION(4096)
#define RO_DATA(align) RO_DATA_SECTION(align)
RO_DATA_SECTION
__param : AT(ADDR(__param) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start___param) = .; \
*(__param) \
VMLINUX_SYMBOL(__stop___param) = .; \
}
}
__MODULE_PARM_TYPE(name, #type)
【3】内核处理:
// Main.c (kernel-3.18\init)
start_kernel(void)
after_dashes = parse_args("Booting kernel", static_command_line, __start___param, __stop___param - __start___param, -1, -1, &unknown_bootoption);
while (*args)
{
parse_one(param, val, doing, params, min_level,in_level, max_level, unknown);
for (i = 0; i < num_params; i++)
err = params[i].ops->set(val, ¶ms[i]);
}
##############################################################################################
一、处理参数方法一:
static int rcorner_cofig = 0;
static int __init set_corner_config(char *str)
{
rcorner_cofig = 1;
pr_err("[wjwind] set_corner_config() rcorner_cofig\n");
return 0;
}
__setup("rcorner", set_corner_config);
或者:
static int __init audit_enable(char *str)
{
audit_default = !!simple_strtol(str, NULL, 0);
if (!audit_default)
audit_initialized = AUDIT_DISABLED;
pr_info("%s\n", audit_default ?
"enabled (after initialization)" : "disabled (until reboot)");
return 1;
}
__setup("audit=", audit_enable);
二、处理参数方法二:
module_param_cb(sense_type, &fg_sense_type_ops, &fg_sense_type, 0644);
static struct kernel_param_ops fg_sense_type_ops = {
.set = fg_sense_type_set,
.get = param_get_int,
};
static int fg_restart_set(const char *val, const struct kernel_param *kp)
int param_get_int(char *buffer, const struct kernel_param *kp);