使用dmesg打印所有日志( 六 )

< 0 || bcon || !console_drivers)preferred_console = selected_console;//设置preferred_console为uboot命令选择的selected_console(即索引)if (newcon->early_setup)//early console没有初始化early_setup字段,以下这个函数不执行newcon->early_setup();//调用serial8250_console_early_setup()if (preferred_console < 0) {if (newcon->index < 0)newcon->index = 0;if (newcon->setup == NULL ||newcon->setup(newcon, NULL) == 0) {newcon->flags |= CON_ENABLED;if (newcon->device) {newcon->flags |= CON_CONSDEV;preferred_console = 0;}}}//传给内核参数://Kernel command line: console=ttyS2,115200n8 rw root=/dev/ram0 initrd=0xc2000000,20M mem=128M ip=192.168.1.220::192.168.1.1:255.255.255.0::eth0:off//所以这里将根据传参console=ttyS2,115200来配置作为console的ttyS2串口for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];i++) {//遍历全局console_cmdline找到匹配的 if (strcmp(console_cmdline[i].name, newcon->name) != 0)//比较终端名称“ttyS”continue;if (newcon->index >= 0 &&newcon->index != console_cmdline[i].index)//console_cmdline[i].index=2 。//比较次设备号continue;if (newcon->index < 0)newcon->index = console_cmdline[i].index;//将终端号赋值给serial8250_console->index#ifdef CONFIG_A11Y_BRAILLE_CONSOLE//没有定义,下边不执行if (console_cmdline[i].brl_options) {newcon->flags |= CON_BRL;braille_register_console(newcon,console_cmdline[i].index,console_cmdline[i].options,console_cmdline[i].brl_options);return;}#endif//console_cmdline[i].options = "115200n8",对于early console而言setup字段未被初始化,故下边的函数不执行if (newcon->setup &&newcon->setup(newcon, console_cmdline[i].options) != 0)//调用serial8250_console_setup()对终端进行配置break;newcon->flags |= CON_ENABLED; //设置标志为CON_ENABLE(这个在printk调用中使用到) newcon->index = console_cmdline[i].index;//设置索引号if (i == selected_console) { //索引号和uboot指定的console的一样 newcon->flags |= CON_CONSDEV;//设置标志CON_CONSDEV(全局console_drivers链表中靠前) preferred_console = selected_console;}break;}//for循环作用大致是查看注册的console是否是uboot知道的引导console,是则设置相关标志和preferred_consoleif (!(newcon->flags & CON_ENABLED))return;if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))//防止重复打印newcon->flags &= ~CON_PRINTBUFFER;acquire_console_sem();if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {//如果是preferred控制台newcon->next = console_drivers;console_drivers = newcon;//添加进全局console_drivers链表前面位置(printk中会遍历该表调用合适的console的write方法打印信息)if (newcon->next)newcon->next->flags &= ~CON_CONSDEV;} else {//如果不是preferred控制台 newcon->next = console_drivers->next;console_drivers->next = newcon; //添加进全局console_drivers链表后面位置}//主册console主要是刷选preferred_console放置在全局console_drivers链表前面,剩下的console放置链表靠后的位置,并设置相应的flags,//console_drivers最终会在printk函数的层层调用中遍历到,并调用console的write方法将信息打印出来if (newcon->flags & CON_PRINTBUFFER) {spin_lock_irqsave(&logbuf_lock, flags);con_start = log_start;spin_unlock_irqrestore(&logbuf_lock, flags);}release_console_sem();if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) {printk(KERN_INFO "console [%s%d] enabled, bootconsole disabled\n",newcon->name, newcon->index);for_each_console(bcon)if (bcon->flags & CON_BOOT)unregister_console(bcon);} else {//调用这里printk(KERN_INFO "%sconsole [%s%d] enabled\n",(newcon->flags & CON_BOOT) ? "boot" : "" ,newcon->name, newcon->index);}}四、在未对console进行初始化之前,内核使用early console进行打印 。之后内核进行真正的console初始化//console_init()在start_kernel()中调用,用来对控制台初始化,这个函数执行完成后,串口可以看到内核用printk()函数打印的信息void __init console_init(void){initcall_t *call;/* Setup the default TTY line discipline. *///此函数调用tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY)//#define N_TTY 0/*struct tty_ldisc_ops tty_ldisc_N_TTY = {.magic= TTY_LDISC_MAGIC,.name= "n_tty",.open= n_tty_open,.close= n_tty_close,.flush_buffer= n_tty_flush_buffer,.chars_in_buffer = n_tty_chars_in_buffer,.read= n_tty_read,.write= n_tty_write,.ioctl= n_tty_ioctl,.set_termios= n_tty_set_termios,.poll= n_tty_poll,.receive_buf= n_tty_receive_buf,.write_wakeup= n_tty_write_wakeup};内核定义一个tty_ldiscs数组,然后根据数组下标来存放对应的线路规程的操作集,而这里的数组下标表示的就是具体的协议,在头文件中已经通过宏定义好了 。例如N_TTY 0 。所以可以发现:ldisc[0] 存放的是N_TTY对应的线路规程操作集ldisc[1]存放的是N_SLIP对应的线路规程操作集ldisc[2]存放的就是N_MOUSE对应的线路规程操作集依次类推 。此处就是ldisc[N_TTY] = tty_ldisc_N_TTY 。int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc){unsigned long flags;int ret = 0;if (disc