1. EPOLL
IO复用的意思是在一个操作里同时监听多个输入输出源,在其中一个或多个输入输出源可用的时候返回,然后对其进行读写操作。
epoll:
- 基于红黑树,使用回调机制,效率高。
- 在内核区和用户区使用共享内存,省去了不必要的内存拷贝。
- 使用epoll没有最大文件描述符的限制。
操作函数:
int epoll_create(); // 创建epoll实例
int epoll_ctl(); // 管理文件描述符
int epoll_wait(); // 检测epoll树中是否有就就绪的文件描述符
- 使用
epoll_ctl()
维护等待队列,在调用epoll_wait()
阻塞进程。
epoll的使用
- 创建监听的套接字
- 将本地IP和端口和套接字绑定
- 给监听的套接字设置监听
- 创建epoll实例对象
- 将用于监听的套接字添加到epoll实例中
- 检测添加到epoll实例中的文件描述符是否就绪,处理已就绪的文件描述符
- 如是监听套接字,和新客户端建立连接,将得到的文件描述符添加到epoll实例中。
- 如是通信套接字,和对应客户端通信,如果连接断开,将文件描述符从epoll实例中删除。
- 在while(1)中循环调用
epoll_wait()
epoll的工作模式
- 水平模式
LT是epoll的缺省模式,在这种做法中,内核通知使用者哪些文件描述符已经就绪了,之后可以对这些就绪的文件描述符进行IO操作了。如果我们不作任何操作,内核还是会继续通知使用者。
特点:
- 读事件:如果文件描述符对应的读缓存区还有数据,读事件就会被触发,epoll_wait()解除阻塞。
- 写事件:如果文件描述符对应的写缓冲区可写,写事件就会被触发,epoll_wait()解除阻塞。
- 边沿模式ET
当文件描述符从未就绪变为就绪时,内核会通过epoll通知使用者。然后不会再为那个文件描述符发送更多的就绪通知。
如果,我们对这个文件描述符做IO操作,从而导致它从就绪态变为未就绪态。当这个未就绪的文件描述符再次变成就绪态,内核会再次通知一次。
边沿模式减少了epoll事件被重复触发的次数,因此效率比LT模式高。
epoll的边沿模式下 epoll_wait()检测到文件描述符有新事件才会通知,如果不是新的事件就不通知,通知的次数比水平模式少,效率比水平模式要高。
2. 服务器并发
- 使用多线程
- 使用多进程
- 使用IO多路转接
- 使用IO多路转接+多线程实现