为了更清楚地解释我想要做什么,我希望我的代码每隔(比方说)2.5 秒检查用户是否输入某些内容(或者另一个非 0 的文件描述符是否有要读取的数据),直到程序停止。
如果用户输入了一些内容,一个简单的
printf()
会通知他,然后程序将再次检查用户是否在接下来的2.5秒内输入了一些内容。
否则,它应该简单地打印时间已用完,然后在接下来的 2.5 秒内再次检查用户输入。
这是我从Beej网络编程指南中窃取并修改以(尝试)满足我的要求的代码片段:
#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;
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
tv.tv_sec = 2;
tv.tv_usec = 500000;
while(1){
select(STDIN+1, &readfds, NULL, NULL, &tv);
if (FD_ISSET(STDIN, &readfds)){
printf("A key was pressed!\n");
tv.tv_sec = 2;
tv.tv_usec = 500000;
}else{
printf("Timed out.\n");
tv.tv_sec = 2;
tv.tv_usec = 500000;
}
}
return 0;
}
只要我不按任何键,它就可以正常工作并打印“超时”。每 2.5 秒一次。但是,如果我输入某些内容,它似乎会忽略用户输入并继续打印“超时”。
另一方面,如果我在无限循环中声明
fd_set
和 struct timeval
inside,一旦我输入某些内容,就会无限地打印出已按下某个键 ,就好像 它会忽略超时。
我不知道为什么这么简单的代码不起作用。我想我遗漏了一些我不知道的文件描述符的要点。
因为你应该重置 ->
FD_ZERO(&readfds)
你的 readfds
并添加文件描述符 -> FD_SET(STDIN, &readfds)
每次 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;
while (1) {
int count; /* how many descriptors are contained in the set. */
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
tv.tv_sec = 2;
tv.tv_usec = 500000;
count = select(STDIN + 1, &readfds, NULL, NULL, &tv);
if ((count > 0) && (FD_ISSET(STDIN, &readfds) != 0)) {
printf("A key was pressed!\n");
} else if (count == -1)
/* check for the error here */
} else {
printf("Timed out.\n");
}
}
return 0;
}
如您所见,您还应该检查
select
的返回值,以检查是否有错误,如果发生错误,然后检查 errno
看看发生了什么,然后检查您感兴趣的文件描述符in 包含在 readfds
中。