为什么无法使用 FD_SET 将 0,1,2 这三个描述符添加到 fd_set 中去呢?

周梦康
  • 8.9k
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>

int main(void)
{
    fd_set     read_set;
    int        fd1, fd2, maxfdp1, res;
    struct     timeval time_val;

    fd1 = open("./test.txt",O_RDONLY);
    fd2 = open("./temp.file",O_RDONLY);
    maxfdp1 = fd2 + 1;

    FD_ZERO(&read_set);
    FD_SET(0, &read_set);
    FD_SET(1, &read_set);
    FD_SET(2, &read_set);
    FD_SET(fd1, &read_set);
    FD_SET(fd2, &read_set);

    time_val.tv_sec = 2;
    time_val.tv_usec = 0;

    res = select(maxfdp1, &read_set, NULL, NULL, &time_val);
    printf("%d\n", res);

    if (res == -1)
    {
        perror("select error:");
    }
    else if (res == 0)
    {
        printf("no fd prepared\n");
    }
    else if (res > 0)
    {
        for (int i = 0; i < maxfdp1; ++i)
        {
            if (FD_ISSET(i, &read_set))
            {
                printf("fd %d in the read_set\n", i);
            }
        }
    }

    return 0;
}

我测试结果

[[email protected] unix]$ gcc select_demo.c -std=c99
[[email protected] unix]$ ./a.out 
2
fd 3 in the read_set
fd 4 in the read_set

为什么0,1,2 这三个都无法添加进去呢?

回复
阅读 3k
1 个回答
zonxin
  • 12.1k
✓ 已被采纳

不是不可以,而是他们根本就没有数据可读(状态没有发生变化)。
select的返回值是在这期间发生状态变化的个数(在这个中是有数据可读的个数)。
0 1 2 分别表示 标准输入,标准输出,标准错误。因为后两个是输出,所有不可能有任何数据给你读,标准输入中你也没有输入数据,所以也没有数据可读。所以只有那两个文件是有数据可读的,所以返回值为2,read_set中只有那两个文件的描述符。
你可以试试这段代码。
读取键盘输入值,超时间隔2.5秒,输出用户输入的字符个数

#include <sys/types.h>   
#include <sys/time.h>   
#include <stdio.h>   
#include <fcntl.h>   
#include <sys/ioctl.h>   
#include <unistd.h>   
  
int main()   
{   
    char buffer[128];   
    int result, nread;   
    fd_set inputs, testfds;   
    struct timeval timeout;   
    FD_ZERO(&inputs);//用select函数之前先把集合清零    
     FD_SET(0,&inputs);//把要检测的句柄——标准输入(0),加入到集合里。  
     while(1)   
    {   
       testfds = inputs;   
       timeout.tv_sec = 2;   
       timeout.tv_usec = 500000;   
       result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout);   
       switch(result)   
       {   
       case 0:   
           printf("timeout/n");   
           break;  
       case -1:   
           perror("select");   
           exit(1);   
       default:   
           if(FD_ISSET(0,&testfds))   
           {   
               ioctl(0,FIONREAD,&nread);//取得从键盘输入字符的个数,包括回车。   
               if(nread == 0)   
               {   
                  printf("keyboard done/n");   
                  exit(0);   
               }   
               nread = read(0,buffer,nread);   
               buffer[nread] = 0;   
               printf("read %d from keyboard: %s", nread, buffer);   
         }   
         break;   
      }   
   }   
   return 0;  
}  
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏