内核中定义了以下全局变量保存启动参数相关的字符串,
/* Untouched command line saved by arch-specific code. */ char __initdata boot_command_line[COMMAND_LINE_SIZE]; /* Untouched saved command line (eg. for /proc) */ char *saved_command_line; /* Command line for parameter parsing */ static char *static_command_line;
#define COMMAND_LINE_SIZE 1024 #define CONFIG_CMDLINE "console=ttySAC0 root=/dev/mtdblock2 rootfstype=cramfs init=/linuxrc" /*may overwritten in parse_tag_cmdline(const struct tag *tag)*/ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; static char __initdata cmd_line[COMMAND_LINE_SIZE];
通过下面的调用关系,default_command_line保存启动参数,由parse_cmdline函数处理后。
asmlinkage void __init start_kernel(void) -->char * command_line; -->setup_arch(&command_line); //setup_arch(char ** cmdline_p) -->char *from = default_command_line; -->parse_cmdline(cmdline_p, from);
parse_cmdline函数只处理通过__early_param(name,fn)宏定义的启动参数,未处理参数保存在command_line[]数组中。
static void __init parse_cmdline(char **cmdline_p, char *from) { char c = ‘ ‘, *to = command_line; int len = 0; for (;;) { if (c == ‘ ‘) { extern struct early_params __early_begin, __early_end; struct early_params *p; for (p = &__early_begin; p < &__early_end; p++) { int len = strlen(p->arg); if (memcmp(from, p->arg, len) == 0) { if (to != command_line) to -= 1; from += len; p->fn(&from); while (*from != ‘ ‘ && *from != ‘\0‘) from++; break; } } } c = *from++; if (!c) break; if (COMMAND_LINE_SIZE <= ++len) break; *to++ = c; } *to = ‘\0‘; *cmdline_p = command_line; }
__early_param(name,fn)宏定义如下,该宏定义的结构体存储在vmlinux.lds.S中指定的early_param.init断中,
__early_begin表示起始地址,__early_end表示结束地址。
/* * Early command line parameters. */ struct early_params { const char *arg; void (*fn)(char **p); }; #define __early_param(name,fn) static struct early_params __early_##fn __used __attribute__((__section__(".early_param.init"))) = { name, fn }