问题
I'm trying to use the select function to accept input but every 2 seconds do something else if the user hasn't entered anything. The code below is waiting two seconds the first time select() is reached but once it prints the first "timed out" message it rapidly keep printing out "timed out" without waiting for 2 seconds, basically entering an infinite loop. Anyone know what the problem is? Thanks for any help.
#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;
}
回答1:
per man: select() may update the timeout argument to indicate how much time was left. pselect() does not change this argument.
This implies that if it times out after 2 seconds it could set your tv_sec to 0.
If both of the fields of timeval are 0 it will return immediately.
Try setting your timeout every loop inside the while() to insure it's not getting overwritten.
回答2:
I do some change based on your code, after select
tv
will be changed.
#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;
}
回答3:
If you ever read the source of select.c in linux kernel, you'll find that in the select() call, the last parameter timeout will be set to zero after it is used.
So, you should set the value of tv inside the loop, before each call of select().
回答4:
If memory serves, the call to select()
can change the value of tv
to indicate the time remaining. You should reinitialize tv
before each call to select()
.
回答5:
You must put
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
into your loop. Assigning: readfds = master;
will not always work (actually I'm pretty sure it will not work in every platform - depending on the definition of fd_et
).
also setting tv
in a loop is a good idea.
来源:https://stackoverflow.com/questions/9494626/c-select-not-waiting-for-timeout-period