一位工作5年的小伙伴在面试的时候被问到IO相关的问题,说,谈谈你对IO多路复用机制的理解。当时,他表示只听说过复用,但不了解具体细节。今天,我就把我的理解分享给大家。1、IO多路复用IO多路复用是一种同步IO模型。使用IO多路复用模型,一个线程可以监听多个文件句柄;一旦一个文件句柄就绪,就可以通知相应的应用程序进行相应的读写操作;当没有文件句柄准备好时,应用程序将被阻塞。从而释放CPU资源。IO可以理解为,在操作系统中,内核态和用户态之间的数据读写操作,大多数情况下指的是网络IO;大多数情况下,多通道是指多个TCP连接,即多个Socket或多个Channel;多路复用是指一个或多个线程资源的多路复用。IO多路复用意味着一个或多个线程处理多个TCP连接。在不创建和维护太多进程/线程的情况下,尽可能减少系统开销。实现IO多路复用的模型有3种,分别是Select、poll和epoll。下面详细介绍三种复用模型的基本原理和优缺点:2.选择模型选择模型的基本原理是使用轮询和遍历。也就是说,客户端在操作服务器时,会创建三个文件描述符,简称FD。它们是writefds(写描述符)、readfds(读描述符)和exceptfds(异常描述符)。而select会阻塞监听这三个文件描述符,当有数据、可读、可写、异常或超时时返回;返回后,通过遍历文件描述符的集合fdset找到就绪的FD,然后,触发相应的IO操作。它的优点是跨平台支持好,几乎所有平台都支持。它的缺点也很明显。由于select采用轮询方式扫描整个磁盘,因此随着fd数量的增加,性能会下降。因此,每次调用select()方法时,都需要将fd集合从用户态复制到内核态并遍历。操作系统对单个进程打开的FD数量有限制,一般默认为1024个。虽然可以通过操作系统的宏定义FD_SETSIZE修改最大FD数量,但是当IO吞吐量巨大。3.poll模型poll模型的原理和select模型基本一样,也是使用轮询和遍历。唯一不同的是poll使用链表来存储fd。所以它的优点是没有最大FD个数的限制。它的缺点和select一样,也是采用轮询方式扫描整个磁盘,随着fd数量的增加也会导致性能下降。4.epoll模型由于select和poll都会因为增加吞吐量而导致性能下降,所以出现了epoll模型。epoll模型使用时间通知机制来触发相关的IO操作。它对FD的个数没有限制,只需要从用户态复制到内核态一次。主要是通过系统底层函数注册和激活FD,从而触发相关的IO操作,极大的提升了性能。主要通过调用以下三个系统函数:(1)epoll_create()函数,系统启动时,会在Linux内核中申请一个B+树结构的文件系统,然后返回epoll对象,也是一个FD。(2)epoll_ctl()函数会在每次创建新连接时同步更新epoll对象中的FD并绑定一个回调函数。(3)epoll_wait()函数轮询所有回调集,触发相应的IO操作。所以epoll模型最大的优势就是把polling改成了callback,大大提高了CPU的执行效率,并且不随着FD的数量而变化。增加导致效率下降。当然它对FD的个数没有限制,也就是说它能支持的FD的上限是操作系统的最大文件句柄数。一般来说,1G内存支持10万个左右的句柄。Redis、Nginx等分布式系统中常用的组件优先使用epoll模型。它的缺点是只能在Linux下运行。5.综合比较下表是三种复用模型的综合比较。感兴趣的朋友可以截图保存,或者从我的竹叶个人资料中获取。好了,以上就是我对IO多路复用机制的理解。
