打开 /var/log/syslog 并使用 poll() 读取数据,但 poll() 总是再次读取相同的数据
Open /var/log/syslog and reading data using poll(), but poll() always reading same data again
测试环境:Ubuntu12.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;
}
简短版本:poll()
不适用于普通文件。 (或者更确切地说,它 有效 但没有做任何有用的事情。)
更长的版本:POLLIN
事件只是意味着,如果您在文件描述符上调用 read()
,它不会阻塞。然而,这对于普通文件总是正确的:如果你在文件的末尾,那么 read()
将立即 return 0。您在这里反复看到相同的数据,因为您每次循环都未能向 dataBuff
添加终止空字节。实际上,read()
没有读取任何超过第一次的数据。
要阻止直到文件被修改,您将需要使用 Linux-特定的 inotify()
API。或者,如果您不需要在新数据出现时立即收到通知,您可以简单地定期尝试读取(例如,每秒一次)并查看是否有新数据可用。
最后一点,警告:并非所有文件系统都支持 inotify()
。特别是,VirtualBox 共享文件夹不支持通知。 (我在这里提到这个是因为它看起来像你在使用 VirtualBox。它不会影响这个 specific 用例,因为 /var/log
不在共享文件夹中,但它是需要注意的事情。)
您的代码按原样运行。
只需添加 memset(dataBuff, 0, 1000);阅读前
测试环境:Ubuntu12.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;
}
简短版本:poll()
不适用于普通文件。 (或者更确切地说,它 有效 但没有做任何有用的事情。)
更长的版本:POLLIN
事件只是意味着,如果您在文件描述符上调用 read()
,它不会阻塞。然而,这对于普通文件总是正确的:如果你在文件的末尾,那么 read()
将立即 return 0。您在这里反复看到相同的数据,因为您每次循环都未能向 dataBuff
添加终止空字节。实际上,read()
没有读取任何超过第一次的数据。
要阻止直到文件被修改,您将需要使用 Linux-特定的 inotify()
API。或者,如果您不需要在新数据出现时立即收到通知,您可以简单地定期尝试读取(例如,每秒一次)并查看是否有新数据可用。
最后一点,警告:并非所有文件系统都支持 inotify()
。特别是,VirtualBox 共享文件夹不支持通知。 (我在这里提到这个是因为它看起来像你在使用 VirtualBox。它不会影响这个 specific 用例,因为 /var/log
不在共享文件夹中,但它是需要注意的事情。)
您的代码按原样运行。 只需添加 memset(dataBuff, 0, 1000);阅读前