C语言 什么会使printk不能立即显示在dmesg中?

nzrxty8p  于 2023-06-21  发布在  其他
关注(0)|答案(4)|浏览(128)

我正在Ubuntu 4.14.12上制作Linux内核模块。
我对printk()的理解是,它保证在运行下一行代码之前立即输出到控制台,而不是将其输出放在最终在某个时候刷新的缓冲区中。是这样吗?
在多次printk调用后,我遇到了一个崩溃,它发生在几百行中,这些调用的输出没有出现在使用-wH命令的dmesg中,也没有出现在通过tee发送到一个文件的dmesg中,我在重新启动后读取了这个文件。
在printk被发送到控制台和它在dmesg中显示的时间之间是否有延迟,这会让我的系统在看到输出之前冻结?还是发生了什么事?
dmesg在修复有问题的代码行后显示有问题的打印。控制台日志级别被设置为高于所讨论的打印的控制台日志级别。

bq8i3lrv

bq8i3lrv1#

我也有类似的情况。在msg的末尾加上\n就好了。

ulmd4ohb

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,等等。

izkcnapc

izkcnapc3#

内核环形缓冲区是行缓冲的,这意味着它在遇到换行符之前不会被刷新,因此将换行符\n添加到msg的末尾。
pr_info("Some message\n");

isr3a4wc

isr3a4wc4#

printk消息被排队到存储器缓冲区,并且用户模式服务必须接收消息并将其输出到文件或systemd-journal。

相关问题