I/O多路复用

  • I/O多路复用的基本概念
  • select,poll,epoll的认识

前言
网络I/O的本质是对socket的读写(文件描述符),一般需要两个阶段
(1)等待数据
(2)数据从内核拷贝到用户空间
网络I/O可分为5种模型
(1)阻塞I/O (2)非阻塞I/O (3)I/O多路复用 (4)信号I/O (5)异步I/O
在多进程或者多线程的情况下,(1)(2)两种I/O会消耗掉大量的系统资源,同时也因为其困难的调度,导致其无法处理高并发的场景,所以引入了I/O多路复用。

I/O多路复用
I/O多路复用是指内核一旦发现一个进程指定的一个或者多个I/O条件准备就绪,它就通知该进程,即集中起来管理socket文件描述符。达到在同一个进程种管理多个socket的功能,这样就避免了大量的进程/线程的创建,减少了系统的开销。其本质是一个同步I/O

select,poll,epoll的简单认识
select,poll,epoll是I/O多路复用的机制,
(1)select
首先将需要监听的socket文件描述符添加到select中,然后阻塞等待select返回,当数据到达时select会返回,用户正式开始进行读写。
这里写图片描述
select使用了一个位图来描述文件描述符的使用情况,判断和操作的对象是一个 set_fd,集合的大小为单个进程可打开的最大文件描述符1024或2048。
不足之处:
a.select每次被调用时,都需要把位图从用户态拷贝到内核态,
b.需要在内核遍历传递进来的fd,存在开销
c.支持的文件描述符个数太小
(2)poll
poll的机制与select非常相似,只是描述文件描述的结构发生了改变。

struct pollfd
{
int fd; //文件描述符
short events;  //等到的事件
short revents;//实际发生的事件
}

采用了这样的结构体数组。其解决了文件描述符个数太少的情况。
但是二者都存在拷贝效率的低下,以及面对大量连接时确定一个文件描述符是否就绪需要遍历的代价。
(3)epoll
epoll作为poll的增强版本。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符事件放入内核到一个事件表中,减少copy的次数。
epool的三个接口

int epoll_create( int size );   //创建epoll句柄,返回一个文件描述符(size参数被忽略)
int epoll_ctl( int epfd, int op, int fd, struct epoll_event* event ); //事件注册函数
int epoll_wait( int epfd, struct epoll_event* events, int maxevents, int timeout );  //等待事件发生

epoll_ctl,每次注册新的事件时会注册到epoll的句柄中,然后把所有fd注册到内核,在epoll_wait中不会重复注册。并为每个fd指定一个回调函数,当设备就绪时,唤醒等待队列。调用回调函数,这个就绪的fd会被添加到就绪队列中去。epoll_wait就是在就绪队列中查看有没有就绪的fd。
select,poll和epoll的区别
操作方式及效率:
select是遍历O(n),poll也是遍历O(n),epoll是回调O(1)
最大连接数:
select为1024/2048,poll,epoll无上限
fd拷贝:
select每次都需要把fd集合从用户态拷贝到内核态;poll每次都需要把fd集合从用户态拷贝到内核态;epoll调用epoll_ctl时拷贝进内核并放到事件表中,单用户进程和内核通过mmap映射共享同一块存储,避免了fd从内核赋值到用户空间。
epoll的两种工作模式
水平触发(LT)
默认工作模式是水平触发,可以延迟处理,或者多次处理
边缘触发(ET)
必须立刻处理,工作模式是非阻塞

猜你喜欢

转载自blog.csdn.net/nuyexiaoxiang/article/details/80110878