【问题标题】:select() call on regular text file's file descriptorselect() 调用常规文本文件的文件描述符
【发布时间】:2013-12-27 19:20:01
【问题描述】:

我遇到了奇怪的问题,每次都选择返回 1 个值。

下面是我的代码:

代码:

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

static int fd;

void *testThread(void* arg)
{
    fd_set set;
    struct timeval tv;
    int test = -1;

    char buf[8]={0};
    int ret = -1;

    while(1)
    {
        FD_ZERO(&set);
        FD_SET(fd,&set);

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

        printf("waiting..\n");
        test = select(fd+1,&set,NULL,NULL,&tv); //FD_SETSIZE
        printf("Value of test = %d\n",test);
        perror("select:");

        if(test == 0)
            printf("No data available to read for last 5 sec.\n");
        else if(test < 0)
            printf("select() failed\n");
        else if(test > 0)
        {
            printf("data available to read\n");
            ret = read(fd,buf,sizeof(buf));
            printf("ret = %d\n",ret);
            printf("%s\n",buf);
            sleep(1);
        }

    }
}

int main()
{
    pthread_t id;
    int ret = -1;
    //FILE *fp = tmpfile();
    char *buf="Hello";
    fd = open("test.txt", O_CREAT |O_RDWR |  O_NDELAY);

    if(0 > fd)
    {
        perror("Failed to open tmp file\n");
        exit(-1);
    }

    printf("Fd %d\n",fd);

    pthread_create(&id,NULL,testThread,(void*)0);
    sleep(5);

    printf("Inside main\n");

    //ret = write(fd,buf,4);
    //printf("value of ret %d\n",ret);
    sleep(20);
    close(fd);

    return 0;
}

在这段代码中,我遇到了奇怪的行为(可能是我在某个地方错了),当我不写入 fd 时,仍然选择返回 1,并打印“可写入的数据”。 我哪里错了?

【问题讨论】:

  • 您期望什么?如果只选择常规文件,您认为select 何时应返回 0?
  • 我已经使用 select 和 socket,但不确定我是否可以将它用于常规文件?我主要担心的是,由于我没有写信给 fd,它仍然会打印“可供读取的数据”。请帮忙。
  • @n.m. select 表明这一点非常有用,例如读取网络安装的常规文件会阻塞。
  • @user4815162342 即使在select 时缓冲区缓存中的数据可用,也不能保证在返回select 和调用read。操作系统中的选择是始终返回“不可读”或“可读”。由于许多程序在标准输入上选择(在正常情况下处理 tty)并且当标准输入是文件时会中断,因此只有“可读”是一个明智的选择。此外,select 并不能保证您不会阻塞(想想锁),只能保证您不会无限期地阻塞。
  • 抱歉,误读了您的评论。不,select 不适用于网络安装的文件。它们始终被视为可用。

标签: c unix select file-io


【解决方案1】:

不幸的是,常规文件上的select 无法按您希望的方式工作——它们总是被认为是可读的,即使在现实块中读取它们时也是如此,就像远程安装的分区一样。这同样适用于poll 和等效的多路复用器。

对任意文件执行非阻塞读取的唯一可移植方式是在单独的线程中执行。另一种方式是使用AIO,费用为additional complexity

【讨论】:

  • 你的答案似乎是写的,只是为了确认选择调用我想知道第一个参数是“我们想要轮询的 fd 的数量”或“最高 fd+1 的值”,例如我有fd1 的值为 4,fd2 的值为 5,那么第一个参数 3(fd1,fd2 和 +1)或 6(fd+1 的最大值)的值应该是多少
  • @SaiyamDoshi manual on Linux 清楚地表明 nfds 是三组中编号最高的文件描述符,加上 1。 所以,你的第二个选项是正确的。
猜你喜欢
  • 2020-09-06
  • 2012-08-07
  • 2013-04-17
  • 1970-01-01
  • 2014-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多