文件流没有新数据时如何防止fgets块

时间:2020-03-06 14:53:14  来源:igfitidea点击:

我有一个执行" tail -f sometextfile"的popen()函数。只要文件流中有数据,显然我可以通过fgets()获取数据。现在,如果没有新数据来自尾部,则fgets()将挂起。我尝试了ferror()和feof()无济于事。当文件流中没有新内容时,如何确保fgets()不会尝试读取数据?

建议之一是select()。由于这是针对Windows平台的,因此select似乎不起作用,因为匿名管道似乎不适用于它(请参阅此文章)。

解决方案

如果我们将POSIX函数用于IO而不是C库,则可以使用select或者poll。

相反,我们可以尝试使用低级IO功能(open(),read()等)读取sometextfile,就像tail本身一样。当没有更多要读取的内容时,read()会返回零,但下次仍将尝试读取更多内容,这与FILE *函数不同。

fgets()是一个阻塞读取,如果没有数据,它应该等到数据可用为止。

我们需要使用select(),poll()或者epoll()执行异步I / O。当有可用数据时,然后从文件描述符执行读取。

这些函数使用" FILE *"句柄的文件描述符,可以通过以下方式检索:" int fd = fileno(f);"。

在Linux(或者任何Unix-y OS)中,可以将popen()使用的基础文件描述符标记为非阻塞。

#include <fcntl.h>

FILE *proc = popen("tail -f /tmp/test.txt", "r");
int fd = fileno(proc);

int flags;
flags = fcntl(fd, F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(fd, F_SETFL, flags);

如果没有可用的输入,则fgets将errno设置为EWOULDBLOCK时返回NULL。

我通过使用线程(特别是_beginthread和_beginthreadex)解决了我的问题。