一.IO多路复用的目的
在linux中IO多路复用的一个目的就是让应用程序在一个进程同时检查多个文件描述符,看这些文件描述符是否准备好了执行IO操作(看IO系统调用是否可以非阻塞地执行)。实际上这些操作都不会执行实际的IO操作,他们只是告诉我们某个文件描述符已经处于就绪状态了,我们需要调用其他的接口来完成实际的IO操作。
在linux中为我们提供了三种技术:select,poll,epoll;
- 1.1 三种技术的优缺点:
优点:select 和 poll存在时间比较长,具有较好的可移植性;
缺点:在同时检查大量的文件描述符时性能延展性不佳;
epoll的优点就是弥补了select和poll在同时检查大量文件描述符性能不佳的问题;缺点就是可移植性较差;
总结:select poll epoll 这三种技术各有优缺点,可根据实际的应用场景选择,后面会介绍他们的实现机制,本篇着重介绍select技术的使用以及实现机制;
二.select的使用方法
- 2.1 select系统调用
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
参数说明:
nfds:检测的最大文件描述符+1;
readfds:检测的读文件描述符集合是否就绪;
writefds:检测的写文件描述符集合是否就绪;
exceptfds:检测的异常文件描述符集合是否就绪;
timeout:用来控制select函数的阻塞行为;
1.如果该参数为NULL,那么select将会一直阻塞,直到有文件描述符准备就绪;
2.=0,select不阻塞,轮询检测是否有文件描述符是否准备就绪;
3.>0,阻塞等待的时间如果超时,则返回错误;
-
2.2 对文件描述符集合操作的宏函数
void FD_CLR(int fd, fd_set *set); //将文件描述符fd,从fd_set中剔除
int FD_ISSET(int fd, fd_set *set); //判断文件描述符是否在fd_set集合中
void FD_SET(int fd, fd_set *set); //将文件描述符添加到fd_set集合中
void FD_ZERO(fd_set *set); //将fd_set集合清空 -
2.3 注意的东西
(1) 参数readfds,writefds,exceptfds是同时作为输入和输出的参数,在使用前,必须使用FD_ZERO和FD_SET将对应的文件描述符集合初始化,然后select调用之后会修改这些结构体,返回的是已经做好准备的描述符集合结构体。通过FD_ISSET来检查。
(2) select函数在阻塞的情况下,有可能被信号打断返回,此种情况需要特别注意; -
2.4 select函数返回值
返回-1表示有错误发生,此时还需要进一步判断返回值是不是EINTR,这种情况就是被信号中断打断的;
返回0,表示select阻塞超时;
返回一个正整数表示有一个或多个文件描述符已经就绪,返回值表示已经就绪的文件描述符的个数;三.内部实现原理
转:http://blog.chinaunix.net/uid-20643761-id-1594860.html
四.select demo