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

时间:2012-02-28 04:20:29

标签: linux logging linux-kernel buffer

我开发了自己的日志处理程序。为了处理源自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()读取并清除了环形缓冲区,我有点相信某些模块会一直向我发送日志。

任何人都可以告诉我 - 读取()清除环形缓冲区吗?

2 个答案:

答案 0 :(得分:5)

成为root用户并运行此cat /proc/kmsg >> File1.txtcat /proc/kmsg >> File2.txt。比较File1.txtFile2.txt您将立即知道在read() cos cat内是否已清除环形缓冲区内部调用read()

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

编辑:我在Jonathan Corbet的book Linux Device Drivers中发现了一些有趣的内容 -

  

printk函数将消息写入循环缓冲区    __ LOG_BUF_LEN 字节长:配置内核时选择 4 KB 1 MB 的值。然后该函数唤醒任何进程   等待消息,即任何正在睡觉的进程    syslog 系统调用或正在读取 / proc / kmsg 。这两个接口   到日志引擎几乎相同,但请注意读取   从/ proc / kmsg消耗来自日志缓冲区的数据,而    syslog 系统调用可以选择返回日志数据,同时保留它   其他过程也是如此。通常,阅读 / proc 文件更容易   并且是 klogd 的默认行为。可以使用 dmesg 命令   查看缓冲区的内容而不刷新它;其实,   该命令是否返回 stdout 缓冲区的全部内容   或者它已被阅读

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

答案 1 :(得分:0)

通过阅读do_syslog功能,消息在阅读时似乎已被清除 根据您的描述,您可以使用klogctl(4)获得相同的行为,这也会清除缓冲区,因此它是有意义的。

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