在kernel/init/main.c文件中定义了此函数:
void __init parse_early_param(void)
{
static __initdata int done = 0;
static __initdata char tmp_cmdline[COMMAND_LINE_SIZE];
if (done)
return;
strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
parse_early_options(tmp_cmdline);
done = 1;
}
此函数在start_kernel中被调用;
boot_command_line在arch/arm/kernel/setup.c中被赋值(strlcpy(boot_command_line,from,COMMAND_LINE_SIZE));
函数parse_early_options定义如下:
void __init
parse_early_options(char *cmdline)
{
parse_args("early options", cmdline, NULL, 0,
do_early_param);
}
通过
parse_args解析命令行参数,同时把参数传入
do_early_param;
static int __init
do_early_param(char *param, char *val)
{
const struct obs_kernel_param *p;
for (p =
__setup_start; p <
__setup_end; p++) { //
遍历了.init.setup段
if ((p->early && strcmp(param, p->str) == 0) || (strcmp(param, "console") == 0 && strcmp(p->str, "earlycon") == 0)) {
if (p->setup_func(val) != 0)
printk(KERN_WARNING"Malformed early option '%s'\n", param);
}
}
/* We accept everything at this stage. */
return 0;
}
__setup_start与__setup_end是/include/asm-generic/vmlinux.lds.h文件中定义的.init.setup段的地址
#define INIT_SETUP(initsetup_align) \
. = ALIGN(initsetup_align); \
VMLINUX_SYMBOL(__setup_start) = .; \
*(.init.setup) \
VMLINUX_SYMBOL(__setup_end) = .;
编译器会根据__used __section(.init.setup)语句编译进该段
其中有两个宏与此相关
__setup与early_param;定义在/include/linux/init.h中
#define
__setup(str, fn) \
__setup_param(str, fn, fn, 0)
#define
early_param(str, fn) \
__setup_param(str, fn, fn, 1)
两个宏都会调用__setup_param
__setup_param宏的定义
#define
__setup_param(str, unique_id, fn, early) \
static const char __setup_str_##unique_id[] __initconst \
__aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
__used __section(.init.setup) \
__attribute__((aligned((sizeof(long))))) \
= { __setup_str_##unique_id, fn, early }
这个宏里面有个结构体obs_kernel_param
struct
obs_kernel_param {
const char *str;
int (*setup_func)(char *);
int early;
};
__setup
与
early_param的区别就是用early标记
函数的调用过程:parse_early_param-->parse_early_options-->parse_args-->do_early_param,
在/init/main.c下可以找到
early_param("debug",debug_kernel);
static const char __setup_str_debug_kernel[] __initconst _aligned(1) = "debug";
static struct obs_kernel_param __setup_debug_kernel __used __section(.init.setup) __attribute__ ((aligned((sizeof(long))))) ={__setup_str_debug_kernel,debug_kernel,1};