什么会使printk不立即出现在dmesg?

问题描述 投票:0回答:1

我在Ubuntu 4.14.12上创建一个Linux内核模块。

我对printk()的理解是保证在下一行代码运行之前立即输出到控制台,而不是将其输出放在最终在某个时刻刷新的缓冲区。它是否正确?

在多个printk调用之后发生了几百行的崩溃,其中输出没有使用-wH命令出现在dmesg中,或者通过tee发送到dmesg中,这是我在重新启动后读取的文件。

printk被发送到控制台的时间和它在dmesg中显示的时间之间会有滞后,这会让我的系统在看到输出之前冻结吗?或者还有其他事情发生了吗?

dmesg在修复有问题的代码行后显示有问题的printks。控制台日志级别设置为高于相关printks的控制台日志级别。

c ubuntu linux-kernel kernel-module
1个回答
0
投票

模块调用printk(...)和控制台上显示的输出之间有很多层。

我对printk()的理解是保证在下一行代码运行之前立即输出到控制台,而不是将其输出放在最终在某个时刻刷新的缓冲区。它是否正确?

不,这不正确。在printk()实现中没有“控制台”,不应该有任何。总有一个缓冲区,多层缓冲区。线1705 in printk.c回答你的问题。 printk_emit()函数使用静态分配的缓冲区static char textbuf[LOG_LINE_MAX];并在其上调用vscnprintf(textbuf, sizeof(textbuf), ...)来解析参数。所以它使用缓冲区。我不认为可以在不使用内部缓冲区的情况下编写printf函数,至少它更难。而__log_buf变量是一个静态分配的缓冲区,一个字符数组,它是内核日志缓冲区。

printk被发送到控制台的时间和它在dmesg中显示的时间之间会有滞后,这会让我的系统在看到输出之前冻结吗?

是?总是存在滞后。我不知道如何定义一个“滞后”(一个毫秒?一秒?一纳秒?)但printk函数背后的汇编指令必须执行,然后所有层直到它们被放置在__log_buf静态变量中。然后在dmesg系统调用等待的read()被唤醒我猜想在console_unlock内部。在唤醒之后,dmesg将最终调用devkmsg_read()函数,该函数将返回缓冲区。然后dmesg()会在收到数据后在stdout上调用write()系统调用。然后write()内核系统调用将尝试在屏幕上写入内容 - 因此数据必须一直通过控制台驱动程序和显示驱动程序和图形驱动程序。总是存在滞后。但它应该是最小的。

dmesg在修复有问题的代码行后显示有问题的printks

这只是说dmesg没有得到内核日志的输出。可能还有其他事情发生。最简单的是dmesg进程没有得到cpu时间,在读取syslog时被阻塞,你的模块在内部执行irq disabled,依此类推。

© www.soinside.com 2019 - 2024. All rights reserved.