我正在Ubuntu 4.14.12上制作Linux内核模块。
我对printk()的理解是,它保证在运行下一行代码之前立即输出到控制台,而不是将其输出放在最终在某个时候刷新的缓冲区中。是这样吗?
在多次printk调用后,我遇到了一个崩溃,它发生在几百行中,这些调用的输出没有出现在使用-wH命令的dmesg中,也没有出现在通过tee发送到一个文件的dmesg中,我在重新启动后读取了这个文件。
在printk被发送到控制台和它在dmesg中显示的时间之间是否有延迟,这会让我的系统在看到输出之前冻结?还是发生了什么事?
dmesg在修复有问题的代码行后显示有问题的打印。控制台日志级别被设置为高于所讨论的打印的控制台日志级别。
4条答案
按热度按时间bq8i3lrv1#
我也有类似的情况。在msg的末尾加上\n就好了。
ulmd4ohb2#
在模块调用
printk(...)
和控制台上显示的输出之间有许多层。我对printk()的理解是,它保证在运行下一行代码之前立即输出到控制台,而不是将其输出放在最终在某个时候刷新的缓冲区中。是这样吗?
不,这是不正确的。在
printk()
实现中没有“控制台”,也不应该有。总有一个缓冲区,很多层的缓冲区。printk. c中的第1705行回答了您的问题。printk_emit()
函数使用静态分配的缓冲区static char textbuf[LOG_LINE_MAX];
,并在其上调用vscnprintf(textbuf, sizeof(textbuf), ...)
来解析参数。所以它使用缓冲器。我认为不使用内部缓冲区是不可能编写printf
函数的,至少它更难。__log_buf
变量是一个静态分配的缓冲区,一个字符数组,它是内核日志缓冲区。在printk被发送到控制台和它在dmesg中显示的时间之间是否有延迟,这会让我的系统在看到输出之前冻结?
怎么了?总是有延迟的。我不知道如何定义“滞后”(一毫秒?一秒钟?一纳秒?)但是
printk
函数后面的汇编指令必须执行,然后所有层都要执行,直到它们被放置在__log_buf静态变量中。然后在read()
系统调用上等待的dmesg
被唤醒了,我猜是在console_unlock的某个地方。在唤醒之后,dmesg
将最终调用devkmsg_read()函数,该函数将返回缓冲区。然后dmesg()
将在接收到数据后在stdout上调用write()
系统调用。然后write()
内核系统调用将尝试在屏幕上写入一些内容-因此数据必须通过控制台驱动程序、显示驱动程序和图形驱动程序。总是有一个滞后。但它应该是最小的。dmesg在修复有问题的代码行后显示有问题的打印
这只是说
dmesg
没有从内核日志中获得输出。可能还有别的事情发生。最简单的是dmesg
进程没有获得cpu时间,在阅读syslog时被阻塞,您的模块在内部执行时禁用irq,等等。izkcnapc3#
内核环形缓冲区是行缓冲的,这意味着它在遇到换行符之前不会被刷新,因此将换行符
\n
添加到msg的末尾。pr_info("Some message\n");
isr3a4wc4#
printk消息被排队到存储器缓冲区,并且用户模式服务必须接收消息并将其输出到文件或systemd-journal。