1.printk基本原理

其实printk的基本原理我是通过韦东山的视频和一篇CSDN博客了解到的

博客链接贴在下面:

嵌入式Linux——printk:printk打印机制分析_静祥阁-CSDN博客_linux printk

博客写得很详细,该博客主要分为如下几个部分:

printk原理/控制台的选择/printk日志级别的设置

最近我在搞问题的时候,代码中涉及到printk的耗时问题,胡跟我说:将打印级别调一调,不显示到串口就不耗时了

那么我的问题是:调整打印级别,那么printk是不打印了还是实际打印了但是我看不到而已?

printk函数调用的子函数的主要脉络如下图:

printk学习之(一):基本原理-编程知识网

从上图可见:红笔隔断,把printk的行为分为两半:将信息记录到log_buf中+调用控制台驱动输出信息

2.将信息记录到log_buf中

实际上vprintk函数中有两个buf

第一个buf: static char printk_buf[1024]; //从这里看printk_buf的大小为1k

这个buf的作用只是将输出信息放入其中:

/* 将输出信息放到printk_buf中,并返回放入字符的个数 */

printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);

第二个buf:log_buf[65536],这个才是真正的循环缓冲区,如果我们没有为printk设置打印级别,最终会往log_buf[]中添加打印级别的,也就是说,通过emit_log_char()函数往log_buf[65536]中写数据,而最终log_buf[65536]中的数据都是带打印级别的

3.调用控制台驱动输出信息

最终release_console_sem()会呼叫到_call_console_drivers(),从如下代码可以看出:

这里可以调用控制台驱动函数__call_console_drivers(),也可以不调用,调用的前提是msg_log_level<console_loglevel

所以这里回答了我开始的问题:

Q:调整打印级别,那么printk是不打印了还是实际打印了但是我看不到而已?

A:适当吊调整打印级别后,不会再调用控制台驱动输出信息,所以也就看不到打印信息了

/** 输出从start 到 end - 1 之间的信息*/
static void _call_console_drivers(unsigned long start,unsigned long end, int msg_log_level)
{if ((msg_log_level < console_loglevel || ignore_loglevel) &&console_drivers && start != end) {if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {/* wrapped write */__call_console_drivers(start & LOG_BUF_MASK,log_buf_len);__call_console_drivers(0, end & LOG_BUF_MASK);} else {__call_console_drivers(start, end);}}
}

4.后记:printk过多带来的性能问题

CSDN:printk打印log过多会导致performance下降_zhouzhengting1的专栏-CSDN博客

printk 分2个阶段, 第一个阶段是将log放到buff, 第二阶段是将buff数据送到uart。Dump log到uart console是一个同步的操作过程。在此期间,IRQ是被disabled,CPU也是在wait,一直到dump完成。由于此阶段的速度会很慢, 并且会把local的irq disable. 所以会导致local cpu sched, 如果在此cpu 的thread都会被block

5.printk的全局示意图

printk学习之(一):基本原理-编程知识网