[linux]select实现非阻塞异步输入


最近要实现一个非阻塞输入的C代码,查到可以通过select函数来完成。
select用于同时监控多个fd,在io可读/写时返回。
正常来说,select是阻塞的,除非超时或者等待的fd内容发生变化。因此,我我们将select的超时时间设为0,便可以非阻塞。按照返回来判断当前监视的fd内容是否变化,从而根据这个返回进行相应的操作。
以下为根据select man page修改的非阻塞输入的代码。
int main(void)
{
fd_set rfds;//fd集合
struct timeval tv;
int retval;
/* Watch stdin (fd 0) to see when it has input. */
/* Wait up to five seconds. */
char c;
char buf[100];
while(1)
{
//select返回后会把以前加入的但并无事件发生的fd清空,则每次开始select前都要重新从array取得fd逐一加入
FD_ZERO(&rfds);
FD_SET(0, &rfds); //监控fd为0,也就是stdin
//FD_ISSET(int fd, fd_set *set);//若存在多个fd,可以用此接口逐个判断
tv.tv_sec = 0; //时间设0,无论fd有没有数据均继续运行
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv); //1 here means (fd=0)+1,see man page
/* Don’t rely on the value of tv now! */
if (retval == -1)
perror(“select()”);
else if (retval)//select检测到有数据之后,通过read读fd=0的数据
{
int ret = 0;
ret = read(0, buf, 100);
if(ret > 0)
{
int i = 0;
for(i = 0;i < ret; i++)
printf(“%c”, buf[i]);
}
//printf(“Data is available now.\n”);
}
/* FD_ISSET(0, &rfds) will be true. */
else//此处为非阻塞正常运行的程序
{
//printf(“No data\n”);
}
retval = 0;
}
exit(EXIT_SUCCESS);
}
,