read() 是否清除内核环形缓冲区 /proc/kmsg?

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

我开发了自己的日志处理程序。为了处理源自

printk()
的日志,我从内核环形缓冲区中读取,如下所示:

#define _PATH_KLOG "/proc/kmsg"
CGR_INT kernelRingBufferFileDescriptor = open(_PATH_KLOG, O_RDONLY|O_NONBLOCK);
CGR_CHAR kernelLogMessage[MAX_KERNEL_RING_BUFFER + 1] = {'\0'};
while (1)
{
    ...
    read(kernelRingBufferFileDescriptor, kernelLogMessage + residueSize, MAX_KERNEL_RING_BUFFER);
    ...
}

我的程序位于用户空间。我记得每当有人使用

read()
读取环形缓冲区中的数据时(就像我上面所做的那样),读取的部分将从环形缓冲区中清除。是这样还是不是?

我对此感到困惑,因为环形缓冲区中总是有一些东西,因此,我的程序非常忙于处理所有这些日志。所以我不确定是因为某些模块不断向我发送日志还是因为我一次又一次地读取相同的日志,因为日志没有清除。

为了弄清楚,我使用

klogctl()
检查环形缓冲区:

CGR_CHAR buf[MAX_KERNEL_RING_BUFFER] = {0};
int byteCount = klogctl(4, buf, MAX_KERNEL_RING_BUFFER - 1);    /* 4 -- Read and clear all messages remaining in the ring buffer */
printf("%s %d: data read from kernel ring buffer = \"%s\"\n",__FILE__, __LINE__, buf);

我一直在获取数据。由于

klogctl()
使用参数 4 读取并清除环形缓冲区,我有点相信某些模块一直在向我发送日志。

谁能告诉我 -

read()
是否清除环形缓冲区?

linux logging linux-kernel buffer
2个回答
5
投票

成为 root 并运行此

cat /proc/kmsg >> File1.txt
cat /proc/kmsg >> File2.txt
。比较
File1.txt
File2.txt
您将立即知道
read()
上的环形缓冲区是否被清除,因为
cat
无论如何都会在内部调用
read()

还可以在此处的内核文档中阅读有关环形缓冲区及其行为方式的信息 - http://www.mjmwired.net/kernel/Documentation/trace/ring-buffer-design.txt

编辑:我在 Jonathan Corbet 的 book

Linux Device Drivers
中发现了一些有趣的东西-

printk 函数将消息写入循环缓冲区 __LOG_BUF_LEN 字节长:配置内核时选择的从 4 KB1 MB 的值。然后该函数会唤醒任何正在运行的进程 等待消息,即任何正在休眠的进程 syslog 系统调用或正在读取 /proc/kmsg。这两个接口 到日志引擎几乎是等价的,但请注意 reading 来自 /proc/kmsg 消耗日志缓冲区中的数据,而 syslog 系统调用可以选择返回日志数据,同时将其保留给 其他流程也是如此。一般来说,读取/proc文件比较容易 是 klogd 的默认行为。可以使用dmesg命令 查看缓冲区的内容而不刷新它;实际上, 该命令返回到stdout缓冲区的全部内容,无论 或者没有已经读过

因此,在您的特定情况下,如果您使用普通的

read()
,我认为缓冲区确实被清除,并且新数据不断写入其中,因此您始终会找到一些数据!内核高手可以在这里指正一下!


0
投票

do_syslog
功能来看,消息一读就被清除了。
根据您的描述,您会得到与
klogctl(4)
相同的行为,这也会清除缓冲区,所以这是有道理的。

所以也许确实有人一直在写信息。
您可以通过文本找到它是哪个

printk
,将其禁用,然后看看您会得到什么。或者您可以将
jiffies
值添加到消息中,这样您就会知道您是否不断收到新消息,或者这些消息是否相同。

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