如何使用select()在普通文件描述符(非套接字)上等待?

11
这是从“man select”中提取的代码示例,再加上几行读取实际正在写入的文件。我怀疑当写入./myfile.txt时,select将返回可以从该fd读取的信息。但事实是只要txt文件存在,select就会在while循环中不断返回。我希望它只在新数据写入文件末尾时返回,我认为它应该这样工作。
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int
main(void)
{
    fd_set rfds;
    struct timeval tv;
    int retval;

    int fd_file = open("/home/myfile.txt", O_RDONLY);

   /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    FD_SET(fd_file, &rfds);

   /* Wait up to five seconds. */
    tv.tv_sec = 5;
    tv.tv_usec = 0;

   while (1)
   {
     retval = select(fd_file+1, &rfds, NULL, NULL, &tv);
     /* Don't rely on the value of tv now! */

     if (retval == -1)
        perror("select()");
     else if (retval)
        printf("Data is available now.\n");
        /* FD_ISSET(0, &rfds) will be true. */
     else
        printf("No data within five seconds.\n");
   }

   exit(EXIT_SUCCESS);
}

那么你的问题是什么?谁说“select”只能在套接字上工作? - cnicutar
问题已编辑,抱歉造成混淆。 - glutz
select 可以用于 任何 文件类型描述符,无论是套接字、文件、管道或任何类似的描述符。但是,您不能使用它来监视文件何时被写入,为此您必须使用一些特定于操作系统的东西,例如在 Linux 上,您可以使用 inotify - Some programmer dude
我理解你评论的第一部分。但是我认为选择套接字的目的基本上只是监听数据何时被写入套接字。对于文件来说有什么不同吗? - glutz
1个回答

18

磁盘文件始终可以读取(但如果您已经在文件末尾,读取可能会返回0字节),因此您不能对磁盘文件使用select()来查找新数据何时被添加到文件中。

POSIX规定:

与普通文件相关联的文件描述符永远选择准备好状态,无论是准备好读、写还是出错条件。

此外,正如cnicutar在一个现已删除的帖子中指出的那样,通常需要在每次迭代中初始化FD_SET。 在您的代码中,您正在监视一个fd,并且该fd始终处于准备好状态,因此实际上FD_SET没有发生变化。 但是,如果您要监视5个描述符,并且select检测到只有一个描述符准备好,则在下一次迭代中,仅监视该一个描述符(除非您重置FD_SET)。 这使得使用select变得棘手。


3
据我所知,poll 不能用于监视常规文件的更改。所以唯一的方法是使用 inotify?问题在于基于 inotify 的解决方案使用文件路径而不是已经打开的文件描述符。 - St.Antario

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接