C++select()没有等待超时时间

C++ select() not waiting for timeout period

本文关键字:等待 超时 时间 C++select      更新时间:2023-10-16

我试图使用select函数来接受输入,但如果用户没有输入任何内容,则每隔2秒执行一次其他操作。下面的代码在第一次到达select()时等待两秒钟,但一旦它打印出第一条"超时"消息,它就会快速地打印出"超时",而不等待2秒钟,基本上进入了一个无限循环。有人知道问题出在哪里吗?谢谢你的帮助。

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
using namespace std;
const int STDIN = 0;
int main(int argc, int *argv[])
{
struct timeval tv;
fd_set readfds, master;
tv.tv_sec = 2;
tv.tv_usec = 0;
FD_ZERO(&readfds);
FD_ZERO(&master);
FD_SET(STDIN, &readfds);
FD_SET(STDIN, &master);
string buffer = "";
while(buffer != "quit"){
    readfds = master;
    if(select(STDIN+1, &readfds, NULL, NULL, &tv) == -1) perror("select");
    if (FD_ISSET(STDIN, &readfds)){
        getline(cin, buffer);
        cout << "You entered: " << buffer << endl;
    }else
        cout << "Timed out.n" << endl;
}
return 0;
}

per-man:select()可以更新timeout参数以指示剩余时间。pselect()不会更改此参数。

这意味着,如果它在2秒钟后超时,它可以将tv_sec设置为0。

如果timeval的两个字段都为0,它将立即返回。

尝试在while()中的每个循环中设置超时,以确保它不会被覆盖。

我根据您的代码进行了一些更改,在select之后,tv将被更改。

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <iostream>
using namespace std;
const int STDIN = 0;
int main(int argc, int *argv[])
{
        struct timeval tv,tv1;
        fd_set readfds, master;
        tv.tv_sec = 2;
        tv.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_ZERO(&master);
        FD_SET(STDIN, &readfds);
        FD_SET(STDIN, &master);
        string buffer = "";
        while(buffer != "quit"){
                readfds = master;
                memcpy(&tv1, &tv, sizeof(tv));
                if(select(STDIN+1, &readfds, NULL, NULL, &tv1) == -1) perror("select");
                if (FD_ISSET(STDIN, &readfds)){
                        getline(cin, buffer);
                        cout << "You entered: " << buffer << endl;
                }else
                        cout << "Timed out.n" << endl;
        }
        return 0;
}

如果你读过linux内核中select.c的源代码,你会发现在select()调用中,最后一个参数超时在使用后会被设置为零。

因此,您应该在每次调用select()之前,在循环中设置tv的值。

如果内存可用,则对select()的调用可以更改tv的值以指示剩余时间。您应该在每次调用select()之前重新初始化tv

您必须放置

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

进入你的循环。赋值:readfds = master;并不总是有效(实际上,我很确定它不会在每个平台上都有效——这取决于fd_et的定义)。在循环中设置CCD_ 9也是一个好主意。