Linux kernel printk的分析(2)

在[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;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/23948.html