转自:http://blog.youkuaiyun.com/guodongping/article/details/9822935
一.printk函数简介
1.printk简介
printk是在内核中运行的向控制台输出显示的函数,Linux内核首先在内核空间分配一个静态缓冲区,作为显示用的空间,然后调用sprintf,格式化显示字符串,最后调用tty_write向终端进行信息的显示
2.printk函数定义
1831 asmlinkage __visible int printk(const char *fmt, ...)
1832 {
1833 va_list args;
1834 int r;
1835
1836 #ifdef CONFIG_KGDB_KDB
1837 if (unlikely(kdb_trap_printk)) {
1838 va_start(args, fmt);
1839 r = vkdb_printf(fmt, args);
1840 va_end(args);
1841 return r;
1842 }
1843 #endif
1844 va_start(args, fmt);
1845 r = vprintk_emit(0, -1, NULL, 0, fmt, args);
1846 va_end(args);
1847
1848 return r;
1849 }
1850 EXPORT_SYMBOL(printk);
其中asmlinkage表示将函数参数存放在局部栈中,va_start和va_end是获取可变参数的方法,该方法读取可变参数的过程其实就是在
堆栈中,使用
指针,遍历
堆栈段中的
参数列表,从低地址到高地址一个一个地把参数内容读出来的过程.
3.vprintk_emit流程
4、console_unlock函数调用流程如下
而con->write就是串口的写函数,它会调用具体的平台串口写函数,将数据写入串口buff中.
二、设置相应串口为调试串口
芯片平台一般会有好几个串口,具体采用哪个串口做为调试串口在uboot或者lk中可以设定,并通过cmdline来告知kernel,kernel在启动时会对cmdline进行解析,根据cmdline的解析结果,调用串口注册函数,对相应的串口进行注册,其相关流程如下:
注意selected_console是个全局变量,串口进行初始化注册时会用到这个全局变量
串口初始化流程如下
regiister_console函数流程如下
从上述流程中可以看出,使用哪个串口做为调试串口,其实就是uboot或者lk发送cmdline知会kernel,kernel使用全局变量selected_console进行标记的