IO模型介绍(select、poll、epoll)
内容提要
IO模型是指输入输出模型,常见的有磁盘IO和网络IO。应用程序不能直接进行读写操作,而是通过操作系统提供的API来进行。IO调用是应用程序向操作系统发起调用,IO执行是操作系统完成IO操作。一次IO流程包括应用程序发起IO调用、操作系统准备数据、数据准备阶段、数据copy阶段。阻塞IO需要不断调用read函数进行系统调用,而非阻塞IO可以通过循环尝试读写文件描述符。多路复用通过select、poll、epoll函数同时监控多个文件描述符,减少线程资源创建。异步IO模型只需要发送一次请求就可以完成状态询问和数据拷贝的操作。同步IO是发出调用后需要参与等待结果的过程,异步IO是发出调用后自己不参与等待。
延伸解读
同步与异步的本质区别
文章指出,同步IO在发出调用后需要自己参与等待结果的过程,而异步IO在发出调用后到数据准备完成期间完全不参与。阻塞、非阻塞、多路复用、信号驱动这四种模型都属于同步IO,因为它们都要求应用程序参与数据拷贝或等待。只有异步IO由内核完成所有操作后主动通知应用。理解这一点有助于避免混淆非阻塞与异步。
多路复用如何减少系统调用
非阻塞IO需要不断轮询调用read,每次都是系统调用,开销很大。多路复用通过select、poll、epoll等函数同时监控多个文件描述符,由内核检测可读状态,就绪后再通知应用发起read。这样避免了为每个文件描述符创建监控线程,也减少了无效的系统调用次数,适合高并发场景。
select、poll与epoll的演进逻辑
select使用固定长度的BitsMap,受FD_SETSIZE限制,默认最多1024个文件描述符,且每次调用需在用户态和内核态间拷贝整个集合,内核和用户态都要遍历。poll改用动态数组,突破了数量限制。epoll则通过红黑树保存文件描述符、事件回调通知和就绪队列,避免了重复拷贝和无效遍历,仅将就绪部分返回用户态,显著提升高并发下的效率。
epoll的触发模式与核心机制
epoll支持水平触发和边缘触发。水平触发下,只要缓冲区有数据,epoll_wait会持续通知;边缘触发下,仅当状态变化时通知一次,因此程序必须一次性读完数据。epoll内部使用红黑树管理事件,通过回调将就绪事件放入就绪队列,epoll_wait直接返回就绪事件,无需用户态再次遍历,从而优化了性能。
Q&A
IO模型的基本概念是什么?
IO模型是输入输出模型,包括磁盘IO和网络IO,应用程序通过操作系统的API进行IO操作。
阻塞IO和非阻塞IO有什么区别?
阻塞IO需要不断调用read函数等待数据,而非阻塞IO通过循环尝试读写文件描述符,第一阶段读未就绪时返回-1。
多路复用的作用是什么?
多路复用通过select、poll、epoll函数同时监控多个文件描述符,减少线程资源创建,提高效率。
epoll相较于select和poll有什么优势?
epoll优化了性能,减少了系统调用的开销,并使用红黑树结构提高事件增删查改的效率。
异步IO模型的工作原理是什么?
异步IO模型只需向内核发送一次请求,内核在数据准备就绪后主动将数据复制到用户空间,并通知应用程序。
同步IO和异步IO的主要区别是什么?
同步IO需要在发出调用后等待结果,而异步IO则在发出调用后不需要参与等待,内核会主动通知应用程序。