一斋

https://lwn.net/Articles/732420/

最近Linus Torvalds突然对printk()的一个修改引起了作者的注意,他可能改变内核日志输出的结果。

大家都知道printk()是内核输出critical message、warnning和debugging信息的方法,它的用法与printf()基本类似,一个区别是printk()打头的参数log level:

printk(KERN_ALERT “CPU on fire: %d\n”, cpu_num);

log level被处理后与格式串一起所以后面不需要逗号。另一个区别也是作者要说的是printk()对不带换行符内容的处理。在Torvalds最近修改之前,故事是不换行的日志被要求使用KERN_CONT log level,然而实现里面却不是这样。

Pavel Machek 8月28日发邮件问道为什么printk(“foo”);printk(“bar”);现在产生的结果变成了”foo\nbar”,原因就是Torvalds近期做的一个修改,Torvalds提到:

  If you want to continue a line, you NEED to use KERN_CONT.
     
     That has always been true. It hasn't always been enforced, though.
    
    If you do two printk's and the second one doesn't say "I'm a continuation", the printk logic assumes you're just confused and wanted two lines.

    很多人反应这个修改直到4.9内核才引入,在这之前有很多期待不换行的用户也没有使用KERN_CONT,原先得到了预期的结果而现在受影响了。Perches也发表了一番抱怨,Torvalds更强硬的回应了一番,具体不表了。

    Torvalds接下来说他想未来完全把一行多次printk()输出取消掉,原因是printk()用环形缓冲区,一行多次输出场景在这个环境里面不太合适。他还建议用户自己缓存多次输出的内容,可能会是以helper function的形式,需要输出一行内容之后再提交给printk()。这样既能使printk及时输出信息的同事记录时间戳和日志级别,又能很好解决现在printk里很讨厌的一些锁相关的问题。

    Steven建议用tracing和/proc文件使用的seq_buf实现helper function,获得了一些支持不过目前还没有实质的ä¿®改。

    总结一下以前一行多次printk()是实现造成的结果,从4.9开始需要用KERN_CONT log level。以后可能对这种情况加一层helper function,这样KERN_CONT就可以完全取消。