本文主要是介绍IO多路复用--select,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
IO多路复用,就是在多个文件描述符上阻塞,并在其中某个fd能用的时候收到通知。
其设计原则是
1: 任何文件描述符准备好IO的时候就告诉我;
2.在没有文件描述符就绪的时候睡觉,这样也不会因为IO而把程序憋死。
3. 在不阻塞的情况下处理所有有收到通知的fd。
常见的方式就是select,poll , epoll。它们有个好处就是可以设置超时,尤其在通讯的IO方面很方便。
函数的造型是 int select(int n,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);
它包含了三个集合,readfds,writefds,errorfds,用户把想监听的fd放入其中,想监听可读信号就仍readfds里面。
然后当你输入的时候内核就通知,用这个宏FD_ISSET(fd,&readfds)来看看fd在不在这个集合里面要在,妥了,直接开始读
示例程序:它监听输出和输入,但是只有你输入一个啥玩意的时候程序才接到消息,不输入它里面没东西,就没法读。
#include<stdio.h> //printf
#include<sys/time.h> //struct timeval
#include<sys/select.h>
#include<unistd.h> //STDOUT_FILENO
#define TIMEOUT 5
#define BUF_LEN 1024
int main(void)
{
struct timeval tv;
fd_set readfds;
fd_set writefds;
int ret;
FD_ZERO(&readfds);
FD_SET(STDIN_FILENO,&readfds);
tv.tv_sec = TIMEOUT;
tv.tv_usec = 0;
int i = 0;
ret = select(STDIN_FILENO+1,&readfds,NULL,NULL,&tv);
if(ret == -1){
perror("select");
return 1;
}else if(!ret){
printf("%d second elapsed.\n",TIMEOUT);
return 0;
}
if(FD_ISSET(STDIN_FILENO,&readfds)){
char buf[BUF_LEN+1];
int len;
len = read(STDIN_FILENO,buf,BUF_LEN);
if(len == -1){
perror("read");
return 1;
}
if(len){
buf[len]='\0';
printf("read : %s\n",buf);
}
return 0;
}
但是select有它性能上的不足,而且也有监听文件上限的不足,当fd的值超过1024限制时,就必须修改FD_SETSIZE的大小,当监听的文件太多了,复制,遍历一遍的开销也不小。但是它的跨平台性是最好的,若一定要用这个,就用多线程来做,每个线程里面分配小于1024个。
这篇关于IO多路复用--select的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!