最近要实现一个非阻塞输入的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);

}