Linux系统中的IO模式

一次IO的两个阶段:

  • Waiting for the data to be ready(等待数据到达内核缓冲区);
  • Copying the data from the kernel to the process(从内核缓冲区拷贝数据到程序缓冲区))

IO模式

模式 特点
阻塞 I/O(blocking IO) 在IO执行的两个阶段都处于blocked(阻塞)状态
非阻塞 I/O(nonblocking IO) 用户进程需要不断的主动询问kernel数据,相当于copy data from kernel to user)依然处于一个阻塞状态
I/O 多路复用( IO multiplexing) 两个阶段的都是阻塞状态,但是可以同时监听多个文件描述符。
信号驱动 I/O( signal driven IO) 在实机生产环境中并不常用
异步 I/O(asynchronous IO) 相比信号驱动IO,异步IO两个阶段都是非阻塞的
  • 阻塞式IO(默认),非阻塞式IO(nonblock),IO复用(select/poll/epoll),signal driven IO(信号驱动IO)都是属于同步型IO。

IO多路复用的机制

机制 特点
select 良好跨平台支持,单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024
poll pollfd并没有最大数量限制(但是数量过大后性能也是会下降)。 和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。
epoll Linux系统专有,在2.6内核中新增。更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。
  • select和poll都需要在返回后,通过遍历文件描述符来获取已经就绪的socket。事实上,同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。
  • select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

epoll的两种模式

  • 边缘触发(ET:edge-triggered):是高速工作模式,只支持no-block socket,当状态有变化或发生了某种事件就发出通知;
  • 水平触发(LT:level triggered):是默认的工作方式,同时支持block和no-block socket,当处于某种状态或具备某种条件就发出通知;
  • ET和LT的区别:LT事件不会丢弃,只要读buffer里面有数据可以让用户读,则会不断通知你。而ET则只在事件发生之时通知。

epoll优点

  • 当检查大量的文件描述符时,epoll的性能延展性比select和poll高很多;
  • epoll API既支持水平触发也支持边缘触发,select和poll只支持水平触发,信号驱动只支持边缘触发;
  • 性能方面,epoll可以避免复杂的信号处理流程;
  • 灵活性高,可以指定我们希望检查的事件类型。

参考

Linux五种IO模型浅谈
Linux IO模式及 select、poll、epoll详解