【问题标题】:does read() clear kernel ring buffer /proc/kmsg?read() 是否清除内核环形缓冲区/proc/kmsg?
【发布时间】:2012-03-17 14:14:05
【问题描述】:

我开发了自己的日志处理程序。为了处理来自 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);

而且我一直在获取数据。由于带有参数 4 的 klogctl() 读取并清除了环形缓冲区,我有点相信某些模块确实一直在向我发送日志。

谁能告诉我 - read() 是否清除环形缓冲区?

【问题讨论】:

    标签: linux logging linux-kernel buffer


    【解决方案1】:

    成为 root 并运行此 cat /proc/kmsg >> File1.txtcat /proc/kmsg >> File2.txt。比较File1.txtFile2.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。这两个接口 到日志引擎几乎是等价的,但请注意 阅读 from /proc/kmsg 使用日志缓冲区中的数据,而 syslog 系统调用可以选择返回日志数据,同时将其留给 其他过程也是如此。一般来说,读取 /proc 文件比较容易 并且是 klogd 的默认行为。可以使用 dmesg 命令 查看缓冲区的内容而不刷新它;实际上, 该命令返回 stdout 缓冲区的全部内容,无论是 是否已经阅读过

    因此,在您的特定情况下,如果您使用的是普通的read(),我认为缓冲区确实被清除了,并且不断向其中写入新数据,因此您一直都能找到一些数据!内核专家可以在这里纠正我!

    【讨论】:

    • 非常有帮助。谢谢。 “然后该函数唤醒任何正在等待消息的进程......”,但在我读取环形缓冲区的代码中,似乎我的程序没有被 printk() 函数唤醒。正确的?另一个问题,“/proc/kmsg”是 FIFO 吗?我知道这不是一个常规文件。
    • @martial 是的 /proc/kmsg 是一个类似于缓冲区的循环 FIFO!
    • @martial 你怎么说printk() 没有唤醒你的功能?如果您的程序无法从proc/kmsg 读取数据,这让您觉得您的程序没有唤醒,那么我认为这是因为您的进程反复输给已经运行的syslogd,它也争相读取/proc /kmsg
    【解决方案2】:

    通过阅读do_syslog 函数,似乎消息在阅读时被清除。
    根据您的描述,您会得到与 klogctl(4) 相同的行为,这也会清除缓冲区,所以这是有道理的。

    所以也许确实有人一直在写消息。
    你可以通过文本找到它是哪个printk,禁用它,然后看看你得到了什么。或者您可以将 jiffies 值添加到消息中,这样您就可以知道您是否不断收到新消息,或者这些消息是否相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-23
      • 1970-01-01
      • 2017-08-31
      • 1970-01-01
      • 2012-04-04
      • 1970-01-01
      相关资源
      最近更新 更多