【问题标题】:Open /var/log/syslog and reading data using poll(), but poll() always reading same data again打开 /var/log/syslog 并使用 poll() 读取数据,但 poll() 总是再次读取相同的数据
【发布时间】:2015-05-21 05:53:58
【问题描述】:

测试环境:Ubuntu 12.04 说明:我做了以下

# `sudo truncate -s 0 /var/log/syslog`
# logger "helloworld".
# `cat /var/log/syslog/`

May 21 11:02:10 setup-VirtualBox setup: `helloworld`

May 21 11:05:01 setup-VirtualBox CRON[3056]: `(root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)`

但是如果我通过下面的程序读取数据,我会重复得到这两行。

有什么问题?

data:May 21 11:02:10 setup-VirtualBox setup: `helloworld`
May 21 11:05:01 setup-VirtualBox CRON[3056]: `(root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)`

data:May 21 11:02:10 setup-VirtualBox setup: `helloworld`
May 21 11:05:01 setup-VirtualBox CRON[3056]: `(root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)`

data:May 21 11:02:10 setup-VirtualBox setup: `helloworld`
May 21 11:05:01 setup-VirtualBox CRON[3056]: `(root) CMD (command -v debian-sa1 > /dev/null && debian-sa1 1 1)`

代码

    #include <stdio.h>
    #include <sys/poll.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    int main()
    {
        int fd = open("/var/log/syslog", O_RDONLY);
        if (fd  == -1)
        {
            perror("open");
            return 0;
        }

        int ret = 0;
        struct pollfd p;
        p.fd = fd;
        p.events = POLLIN;
        char dataBuff[1000];
        memset(dataBuff, 0, 1000);
        int i = 0;
        int numEvents = 0;
        /* wait for events */
        while (1) 
        {
            numEvents = poll(&p, 1, -1);
            if (numEvents > 0) 
            {
                if (0 != (POLLIN & p.revents))
                {
                    ret = read(p.fd, dataBuff,1000);
                    if (ret > 0)
                    {
                        fprintf(stderr, "data:%s\n",dataBuff);
                    }
                }
            }
        }
        return 0;
    }

【问题讨论】:

    标签: linux system-calls epoll


    【解决方案1】:

    短版:poll() 不适用于普通文件。 (或者更确切地说,它有效,但没有做任何有用的事情。)

    更长的版本:POLLIN 事件仅仅意味着,如果你在文件描述符上调用read(),它不会阻塞。但是,对于普通文件来说总是如此:如果你在文件的末尾,那么read() 将立即返回 0。您在这里反复看到相同的数据,因为您每次循环时都未能将终止空字节添加到dataBuff。实际上,read() 不会在第一次之后读取任何数据。

    要阻止直到文件被修改,您需要使用 Linux 特定的inotify() API。或者,如果您不需要在出现新数据时立即收到通知,您可以简单地尝试定期读取(例如,每秒一次)并查看是否有新数据可用。


    作为最后一点,警告:并非所有文件系统都支持inotify()。特别是,VirtualBox 共享文件夹不支持通知。 (我在这里提到这一点是因为看起来您正在使用 VirtualBox。它不会影响这个 特定 用例,因为 /var/log 不在共享文件夹中,但需要注意.)

    【讨论】:

    • 感谢您的意见。我在这里添加了终止NULL。它有效。
    【解决方案2】:

    您的代码按原样运行。 只需添加一个添加 memset(dataBuff, 0, 1000);阅读前

    【讨论】:

    • 它与这种变化“有效”,但显然不是按照预期的方式。 (由于我的回答中解释的原因,poll() 没有返回有用的数据。)
    • 我验证了你所说的@duskwuff。是的,你是对的。 POLLIN 在正常文件情况下始终为真。所以我需要去inotify。不错的输入。感谢您的信息。
    猜你喜欢
    • 2011-12-14
    • 2020-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    相关资源
    最近更新 更多