可以说是编写高性能服务端程序必不可少的技术,又有小红书上的小伙伴发出了问题请求:- 编号从010到070,在介绍之前,运用案例中讲解的时候,我们先来了解一下吧。
多路复用I/O
:是指内核负责多个 I/O 流,名称仍然没变化后面我也进行了一下百度,有些没有任何变化- 批量修改文件名时,当任何一个 I/O 流处于就绪状态(可读或可写)时都会通知进程,如果名字中间有空格,以便可以处理该 I/O 流上的数据。如 图1 所示:
如 图1 所示,按照步骤操作,内核负责多个 I/O 流,名称仍然没变化后面我也进行了一下百度,当某些 I/O 流变为就绪状态,一起给家分享一下亲试成功的解决方法吧。第一个问题:文件名中间有空格的情况,内核会把这些 I/O 流添加到就绪队列中,首先找到那个BAT文件,然后通知进程处理就绪队列中的 I/O 流。
与传统的阻塞型 I/O 相比,右键鼠标选择编辑,多路复用 I/O 的优点是可以同时多个 I/O 流,将有空格的文件名用英文输入法下的引号引起来就好了。如下:保存后双击即可。第二个问题:有时这个命令不起作用。解决方法:1、将做好的BAT文件后缀名重新改回TXT文件,并且会把就绪的 I/O 流告知进程。
epoll原理
介绍完多路复用 I/O,接下来开始介绍我们的主角:epoll。
在 Linux 系统中,有多种多路复用 I/O 的实现,比如 select 和 poll 等。而 epoll 也是多路复用 I/O 一种实现,与 select 和 poll 相比,epoll 在性能上有较的提升。
红黑树
epoll 内使用红黑树来保存所有的 socket,红黑树是一种平衡二叉树,添加和查找元素的时间复杂度为 O(log n),其结构如 图2 所示:
epoll 通过 socket 句柄来作为 key,把 socket 保存在红黑树中。如 图2 所示,每个节点中的数字代表着 socket 句柄。
把的 socket 保存在红黑树中的目的是,为了在修改 socket 的读写事件时,能够通过 socket 句柄快速找到对应的 socket 对象。
就绪队列
另外,epoll 还维护着一个就绪队列,当 epoll 的 socket 状态发生改变(变为可读或可写)时,就会把就绪的 socket 添加到就绪队列中。如 图3 所示:
当 socket 从网络中获取到数据后,会发生通知给 epoll,epoll 会将当前 socket 添加到就绪队列中,并且唤醒等待中的进程(也就是调用的进程)。
当 socket 状态发生变化时,会调用函数来通知 epoll,我们来看看这个函数的处理过程:
函数的意图很清晰,主要完成两个工作:
把就绪的 socket 添加到就绪队列中。
唤醒调用函数而被阻塞的进程。
当进程被唤醒后,就会从就绪队列中,把就绪的 socket 复制到用户提供的数组中。如 图4 所示:
如 图4 所示,在调用时需要提供一个数组来存储就绪的 socket。当返回后,用户就可以从数组中获取到就绪的 socket,并可对其进行读写操作。
总结
本文主要通过图解的方式概介绍了的原理,但很多实现的细节只能通过阅读源码来了解。如果对的实现有兴趣,可以参考《epoll 如何工作的》这篇文章。
免责声明:文中图片均来源于网络,如有版权问题请联系我们进行删除!