在[printk.c]里面有一个很重要的语句 __setup("console=", console_setup);这句话也就是说当CONFIG_CMDLINE含有"console="字符的话,就调用console_setup函数, 所以在parse_options调用的时候,
就会调用到 console_setup函数, console_setup就会记录下来console驱动的name,以及一些选项参数到console_cmdline数组中(如波特率),设置 preferred_console参数,这样console driver已经选择好一半了.
console_setup()
{
..............
for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
if (strcmp(console_cmdline[i].name, name) == 0 &&
console_cmdline[i].index == idx) {
preferred_console = i;
return 1;
}
if (i == MAX_CMDLINECONSOLES)
return 1;
preferred_console = i;
c = &console_cmdline[i];
memcpy(c->name, name, sizeof(c->name));
c->options = options;
c->index = idx;
..............
}
选择console driver的另一半来自于register_console(linux启动后也会调用此函数),register_console
最重要的一句话是console->next = console_drivers;这样就完成了选择console driver的全过程.
void register_console(struct console * console)
{
..............
//找到console_driver的过程
for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
if (strcmp(console_cmdline[i].name, console->name) != 0)
continue;
if (console->index >= 0 &&
console->index != console_cmdline[i].index)
continue;
if (console->index < 0)
console->index = console_cmdline[i].index;
if (console->setup &&
console->setup(console, console_cmdline[i].options) != 0) //此时做了setup的动作.
break;
console->flags |= CON_ENABLED;
console->index = console_cmdline[i].index;
if (i == preferred_console)
console->flags |= CON_CONSDEV;
break;
}
if (!(console->flags & CON_ENABLED))
return; //屏蔽掉其他非console的driver
if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
console->next = console_drivers;
console_drivers = console; //设定console_driver
} else {
console->next = console_drivers->next;
console_drivers->next = console;
}
..............
}
[后记]
bootloader也可以传递参数给Kernel, 原理就是bootloader向一块内存中写入具有特定结构的数据,然后Kernel在调用时分析此内存数据,最后也会放到标准command_line缓存中,像上面一样处理.
[Setup.c]
__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
static int __init parse_tag_cmdline(const struct tag *tag)
{
strncpy(default_command_line, tag->u.cmdline.cmdline, COMMAND_LINE_SIZE);
default_command_line[COMMAND_LINE_SIZE - 1] = '\0'; //放到default_command_line中
return 0;
}