printk如何定向输出到UART的?


我们通常在config里面配置这么一句“CONFIG_CMDLINE="console=tty0 console=ttyMT3,921600n1 root=/dev/ram"”,然后修改console的赋值就可以改变输出的位置,代码中如何实现的呢?

这里紧接着上文中的printk.c文件中,有这么一个函数先看一下:
/*
 * Set up a list of consoles.  Called from init/main.c
 */
拉风的注释直接告诉了我们这个函数被init/main.c文件中某个函数调用。
  1. static int __init console_setup(char *str)  
  2. {  
  3.     char buf[sizeof(console_cmdline[0].name) + 4]; /* 4 for index */  
  4.     char *s, *options, *brl_options = NULL;  
  5.     int idx;  
  6.   
  7.   
  8. #ifdef CONFIG_A11Y_BRAILLE_CONSOLE   
  9.     if (!memcmp(str, "brl,", 4)) {  
  10.         brl_options = "";  
  11.         str += 4;  
  12.     } else if (!memcmp(str, "brl=", 4)) {  
  13.         brl_options = str + 4;  
  14.         str = strchr(brl_options, ',');  
  15.         if (!str) {  
  16.             printk(KERN_ERR "need port name after brl=\n");  
  17.             return 1;  
  18.         }  
  19.         *(str++) = 0;  
  20.     }  
  21. #endif   
  22.   
  23.   
  24.     /* 
  25.      * Decode str into name, index, options. 
  26.      */  
  27.     if (str[0] >= '0' && str[0] <= '9') {  
  28.         strcpy(buf, "ttyS");  
  29.         strncpy(buf + 4, str, sizeof(buf) - 5);  
  30.     } else {  
  31.         strncpy(buf, str, sizeof(buf) - 1);  
  32.     }  
  33.     buf[sizeof(buf) - 1] = 0;  
  34.     if ((options = strchr(str, ',')) != NULL)  
  35.         *(options++) = 0;  
  36. #ifdef __sparc__   
  37.     if (!strcmp(str, "ttya"))  
  38.         strcpy(buf, "ttyS0");  
  39.     if (!strcmp(str, "ttyb"))  
  40.         strcpy(buf, "ttyS1");  
  41. #endif   
  42.     for (s = buf; *s; s++)  
  43.         if ((*s >= '0' && *s <= '9') || *s == ',')  
  44.             break;  
  45.     idx = simple_strtoul(s, NULL, 10);  
  46.     *s = 0;  
  47.   
  48.   
  49.     __add_preferred_console(buf, idx, options, brl_options);  
  50.     console_set_on_cmdline = 1;  
  51.     return 1;  
  52. }  
可以看到这里面有对字符串的解析,获得tty的name,index,options。加入链表是由下面的宏来做的。
  1. __setup("console=", console_setup);  
好像是不是缺少了点东东,在main.c中调用的的链表呢?在这里register_console()。
 
  1. /* 
  2.  * The console driver calls this routine during kernel initialization 
  3.  * to register the console printing procedure with printk() and to 
  4.  * print any messages that were printed by the kernel before the 
  5.  * console driver was initialized. 
  6.  * 
  7.  * This can happen pretty early during the boot process (because of 
  8.  * early_printk) - sometimes before setup_arch() completes - be careful 
  9.  * of what kernel features are used - they may not be initialised yet. 
  10.  * 
  11.  * There are two types of consoles - bootconsoles (early_printk) and 
  12.  * "real" consoles (everything which is not a bootconsole) which are 
  13.  * handled differently. 
  14.  *  - Any number of bootconsoles can be registered at any time. 
  15.  *  - As soon as a "real" console is registered, all bootconsoles 
  16.  *    will be unregistered automatically. 
  17.  *  - Once a "real" console is registered, any attempt to register a 
  18.  *    bootconsoles will be rejected 
  19.  */  
  20. void register_console(struct console *newcon)  
  21. {  
  22.     ............................  
  23.     /* 
  24.      *  See if this console matches one we selected on 
  25.      *  the command line. 
  26.      */  
  27.      //看上面的注释我们也可以知道了command line中的定义在这里也起作用了   
  28.     for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];  
  29.             i++) {  
  30.         if (strcmp(console_cmdline[i].name, newcon->name) != 0)  
  31.             continue;  
  32.         if (newcon->index >= 0 &&  
  33.             newcon->index != console_cmdline[i].index)  
  34.             continue;  
  35.         if (newcon->index < 0)  
  36.             newcon->index = console_cmdline[i].index;  
  37. #ifdef CONFIG_A11Y_BRAILLE_CONSOLE   
  38.         if (console_cmdline[i].brl_options) {  
  39.             newcon->flags |= CON_BRL;  
  40.             braille_register_console(newcon,  
  41.                     console_cmdline[i].index,  
  42.                     console_cmdline[i].options,  
  43.                     console_cmdline[i].brl_options);  
  44.             return;  
  45.         }  
  46. #endif   
  47.         if (newcon->setup &&  
  48.             newcon->setup(newcon, console_cmdline[i].options) != 0)/////在这里可以看到setup的过程了   
  49.             break;  
  50.         newcon->flags |= CON_ENABLED;  
  51.         newcon->index = console_cmdline[i].index;  
  52.         if (i == selected_console) {  
  53.             newcon->flags |= CON_CONSDEV;  
  54.             preferred_console = selected_console;  
  55.         }  
  56.         break;  
  57.     }  
  58.   
  59.   
  60.     if (!(newcon->flags & CON_ENABLED))//其他的console driver屏蔽掉   
  61.         return;  
  62.   
  63.   
  64. ........................................  
  65. }  
当然了,上面的函数在源码中的注释很是详细,如果需要看的,读源码是最佳的选择。

到了这里,so command line的tty端口的指定就到了这里了。

相关内容