C ++ select () не ожидает периода ожидания - PullRequest
4 голосов
/ 29 февраля 2012

Я пытаюсь использовать функцию выбора, чтобы принять ввод, но каждые 2 секунды делают что-то еще, если пользователь ничего не вводил.Приведенный ниже код ждет две секунды при первом достижении select (), но как только он напечатает первое сообщение «timed out», он быстро продолжит печатать «timed out», не дожидаясь 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;
}

Ответы [ 5 ]

14 голосов
/ 29 февраля 2012

на человека: select () может обновить аргумент времени ожидания, чтобы указать, сколько времени осталось.pselect () не изменяет этот аргумент.

Это означает, что если время ожидания истечет через 2 секунды, он может установить значение tv_sec равным 0.

Если оба поля timeval равны 0, это будетнемедленно вернитесь.

Попробуйте установить время ожидания для каждого цикла в while (), чтобы убедиться, что оно не перезаписывается.

2 голосов
/ 29 февраля 2012

Я делаю некоторые изменения в зависимости от вашего кода, после того как 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;
}
1 голос
/ 29 февраля 2012

Вы должны поставить

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

в вашу петлю. Назначение: readfds = master; не всегда будет работать (на самом деле я уверен, что это не будет работать на каждой платформе - в зависимости от определения fd_et). также установка tv в цикле - хорошая идея.

1 голос
/ 29 февраля 2012

Если память не изменяет, вызов select() может изменить значение tv, чтобы указать оставшееся время.Вы должны повторно инициализировать tv перед каждым вызовом select().

1 голос
/ 29 февраля 2012

Если вы когда-нибудь прочитаете источник select.c в ядре Linux, вы обнаружите, что при вызове select () время ожидания последнего параметра будет установлено равным нулю после его использования.

ИтакВы должны установить значение tv внутри цикла перед каждым вызовом select ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...