#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/select.h>
#include <sys/time.h>
int main(void)
{
fd_set read_set;
int fd1, fd2, maxfdp1, res;
struct timeval time_val;
fd1 = open("./test.txt",O_RDONLY);
fd2 = open("./temp.file",O_RDONLY);
maxfdp1 = fd2 + 1;
FD_ZERO(&read_set);
FD_SET(0, &read_set);
FD_SET(1, &read_set);
FD_SET(2, &read_set);
FD_SET(fd1, &read_set);
FD_SET(fd2, &read_set);
time_val.tv_sec = 2;
time_val.tv_usec = 0;
res = select(maxfdp1, &read_set, NULL, NULL, &time_val);
printf("%d\n", res);
if (res == -1)
{
perror("select error:");
}
else if (res == 0)
{
printf("no fd prepared\n");
}
else if (res > 0)
{
for (int i = 0; i < maxfdp1; ++i)
{
if (FD_ISSET(i, &read_set))
{
printf("fd %d in the read_set\n", i);
}
}
}
return 0;
}
我测试结果
[zhoumengkang@localhost unix]$ gcc select_demo.c -std=c99
[zhoumengkang@localhost unix]$ ./a.out
2
fd 3 in the read_set
fd 4 in the read_set
为什么0,1,2 这三个都无法添加进去呢?
不是不可以,而是他们根本就没有数据可读(状态没有发生变化)。select
的返回值是在这期间发生状态变化的个数(在这个中是有数据可读的个数)。
0 1 2 分别表示 标准输入,标准输出,标准错误。因为后两个是输出,所有不可能有任何数据给你读,标准输入中你也没有输入数据,所以也没有数据可读。所以只有那两个文件是有数据可读的,所以返回值为2,read_set
中只有那两个文件的描述符。
你可以试试这段代码。
读取键盘输入值,超时间隔2.5秒,输出用户输入的字符个数
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main()
{
char buffer[128];
int result, nread;
fd_set inputs, testfds;
struct timeval timeout;
FD_ZERO(&inputs);//用select函数之前先把集合清零
FD_SET(0,&inputs);//把要检测的句柄——标准输入(0),加入到集合里。
while(1)
{
testfds = inputs;
timeout.tv_sec = 2;
timeout.tv_usec = 500000;
result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout);
switch(result)
{
case 0:
printf("timeout/n");
break;
case -1:
perror("select");
exit(1);
default:
if(FD_ISSET(0,&testfds))
{
ioctl(0,FIONREAD,&nread);//取得从键盘输入字符的个数,包括回车。
if(nread == 0)
{
printf("keyboard done/n");
exit(0);
}
nread = read(0,buffer,nread);
buffer[nread] = 0;
printf("read %d from keyboard: %s", nread, buffer);
}
break;
}
}
return 0;
}