如何使read()无阻塞和重置read()

时间:2016-01-08 23:59:26

标签: c select

所以我做了这个函数,就像倒计时一样。我想在倒计时减少时读取一个命令。我的一个大问题是让read()等待输入,而倒计时正在减少。你可以看到我尝试使用select(),但在第一个printf("timeout.\n");后它停止尝试阅读。我只在timeout做了一次演出,否则它会一直持续到倒计时达到0.我需要再次尝试阅读。

int timer(int seconds) 
{
    time_t start, end;
    double elapsed;
    int opened=0; 
    char command[10];
    struct timeval tv;
    int fd_stdin,rv;
    fd_set rd;

    fd_stdin=fileno(stdin);

    FD_ZERO(&rd);
    FD_SET(fileno(stdin),&rd);

    tv.tv_sec=5;
    tv.tv_usec=0;

    time(&start);  /* start the timer */

    do
    {
        time(&end);

        elapsed = difftime(end, start);

        if(fmod(elapsed,5)==0)
        {
            printf("Time remaining: %f minutes.\n", (seconds-elapsed)/60);
            sleep(1);
            if(opened==0)
            {
                printf("Use opentest to open your test.\n");
                opened=1;
            }
            fflush(stdout);
        }
        int c;
        rv=select(fd_stdin+1,&rd,NULL,NULL,&tv);
        if(rv==-1)
        {
            perror("Error on select.\n");
            exit(1);
        }
        else if (rv==0 && c!=1)
        {
            printf("timeout.\n");
            rv=select(fd_stdin+1,&rd,NULL,NULL,&tv);
            c=1;
        }
        else 
        {
            c=0;
            read(fd_stdin,command,10);
        }
    }
    while(elapsed < seconds);
    return 0;
}

编辑:要使用fmod()函数,我编译如下:gcc client.c -lm -o client.exe。我不认为这是问题,但我不确定。

1 个答案:

答案 0 :(得分:1)

select()在退出时修改fd_set以反映已发出信号的描述符。您没有在每次超时后重置fd_set

此外,在某些平台上,select()会修改timeval结构以反映剩余时间,因此每次调用{{1}时都必须重置timeval在那些平台上。

此外,您的select()变量在循环内声明并且未初始化。把它移到循环外面。

尝试更像这样的事情:

c