一、简述
IO 多路复用是一种同步 IO 模型,实现一个线程可以监视多个文件描述符的IO通道,一旦监控的文件,一但监控的文件描述IO通道有数据发生,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序。
IO 多路复用的三种实现方式:select、poll、epoll
二、select 机制
- 先构造一张有关描述符的表,然后调用一个函数(select)。当这些文件描述符中的一个或多个已准备好进行I/O时函数才返回。
- 函数返回时告诉进程那个描述符已就绪,可以进行I/O操作。
1.创建文件描述符的集合
fd_set rdfs;
2.清空文件描述符的集合
FD_ZERO(&rdfs);
3.将要监控的文件描述符0加入到集合中
FD_SET(0,&rdfs);
4.设置select等待时间
struct timeval myval;
myval.tv_sec=5;
myval.tv_usec=0;
5.select函数
返回值:<0 表示出错
=0 表示超时
>0 文件描述符有数据可读
int reval=select(1,&rdfs,NULL,NULL,&myval);
if(reval<0)
{
perror("select error");
}else if(reval==0) //超时
{
printf("select timeout\n");
}else if(reval>0)
{
if(FD_ISSET(0,&rdfs)) //判断文件描述符0在集合的值是否为1 (是否可读)
{
char buf[20]={'\0'};
read(0,buf,sizeof(buf));
printf("read:%s",buf);
}
}
}
int select(int n, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds, struct timeval *timeout);
- maxfd
- 所有监控的文件描述符中最大的那一个加1
- read_fds
- 所有要读的文件文件描述符的集合
- write_fds
- 所有要的写文件文件描述符的集合
- except_fds
- 其他要向我们通知的文件描述符
- timeout
- 超时设置.
- NULL:一直阻塞,直到有文件描述符就绪或出错
- 时间值为0:仅仅检测文件描述符集的状态,然后立即返回
- 时间值不为0:在指定时间内,如果没有事件发生,则超时返回。
优点:
1. 跨平台
2. 代码简单,易于维护
3. 时间精度高,用于特殊场景
缺点:
4. 轮询监听socket是否有时间发生,浪费CPU资源
5. 最大监听上线为1024个socket,因为是轮询,所以不能监听太多socket防止不能及时响应消息。
6. 只返回就绪数量,需要用户轮序查看具体是哪些有事件发生。
7. select每一次监听都需要将监听队列重新加载到监听队列,浪费不必要的拷贝开销