如何在循环内正确使用select?

问题描述

我正在尝试修改发现的示例。

示例:

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define STDIN 0  // file descriptor for standard input

int main(void)
{
   struct timeval tv;
   fd_set readfds;

   tv.tv_sec = 2;
   tv.tv_usec = 500000;

   FD_ZERO(&readfds);
   FD_SET(STDIN,&readfds);

   // don't care about writefds and exceptfds:
   select(STDIN+1,&readfds,NULL,&tv);

   if (FD_ISSET(STDIN,&readfds))
       printf("A key was pressed!\n");
   else
       printf("Timed out.\n");

   return 0;
}

如果在2.5秒内没有发送消息,则打印超时,否则按下了打印键。

我试图将其放入while循环中:

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#define STDIN 0  // file descriptor for standard input

int main(void)
{
   fd_set readfds,temp;
   struct timeval tv;

   FD_ZERO(&readfds);
   FD_ZERO(&temp);
   FD_SET(STDIN,&readfds);

   while(1){
       
   temp = readfds;     
   tv.tv_sec = 2;
   tv.tv_usec = 500000;
   // don't care about writefds and exceptfds:
   if (select(STDIN+1,&temp,&tv) == -1)
       printf("err");

   if (FD_ISSET(STDIN,&temp))
   {
       printf("A key was pressed!\n");
   }
   else
       printf("Timed out.\n");
   }
   return 0;
} 

在此代码中,当我输入一个键时,它将一直打印一个键,直到永远被按下。

我在线阅读,每次都必须设置电视变量,但仍然无济于事。

我是否需要临时fd_set ?我怎么了?

解决方法

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>

                // Note: STDIN_FILENO,or fileno(stdin)
#define STDIN 0  // file descriptor for standard input

int main(void)
{
   fd_set readfds,temp;
   struct timeval tv;
   int ret,ch;

   FD_ZERO(&readfds);
   FD_ZERO(&temp);
   FD_SET(STDIN,&readfds);

   while(1){

        temp = readfds;
        tv.tv_sec = 2;
        tv.tv_usec = 500000;
        // don't care about writefds and exceptfds:
        ret = select(STDIN+1,&temp,NULL,&tv) ;
        if (ret == -1) {
                if (errno == EAGAIN) continue; // These are NOT Errors,but natural occuring events
                if (errno == EINTR) continue; // The are reported to avoid your select() to block for too long
                        perror("erreur");
                break;
                }
        else if (ret ==0) {
           printf("Timed out.\n");
                continue;
                }
                // Ok: select has returned > 0; there must be something to read
        if (FD_ISSET(STDIN,&temp)) {
                ch = getc(stdin); // Lookout: stdin is line-buffered
                printf("A key was pressed: %d!\n",ch);
                }
        }
   return 0;
}