3)调用epoll_wait收集发生的事件的连接
如此一来,要实现上面说是的场景,只需要在进程启动时建立一个epoll对象,然后在需要的时候向这个e 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 poll对象中添加或者删除连接。同时,epoll_wait的效率也非常高,因为调用epoll_wait时,并没有一股脑的向操作系统复制这100万个连接的句柄数据,内核也不需要去遍历全部的连接。
Epoll 很重要,但是 Epoll 与 Select 的区别是什么呢?Epoll 高效的原因是什么?
从网卡接收数据说起
下边是一个典型的计算机结构图,计算机由 CPU、存储器(内存)与网络接口等部件组成,了解 Epoll 本质的第一步,要从硬件的角度看计算机怎样接收网络数据。
计算机结构图(图片来源:Linux 内核完全注释之微型计算机组成结构)
下图展示了网卡接收数据的过程:
-
在 1 阶段,网卡收到网线传来的数据。
-
经过 2 阶段的硬件电路的传输。
-
最终 3 阶段将数据写入到内存中的某个地址上。
这个过程涉及到 DMA 传输、IO 通路选择等硬件有关的知识,但我们只需知道:网卡会把接收到的数据写入内存。
网卡接收数据的过程
通过硬件传输,网卡接收的数据存放到内存中,操作系统就可以去读取它们。
如何知道接收了数据?
了解 Epoll 本质的第二步,要从 CPU 的角度来看数据接收。理解这个问题,要先了解一个概念:中断。
计算机执行程序时,会有优先级的需求。比如,当计算机收到断电信号时,它应立即去保存数据,保存数据的程序具有较高的优先级(电容可以保存少许电量,供 CPU 运行很短的一小段时间)。
一般而言,由硬件产生的信号需要 CPU 立马做出回应,不然数据可能就丢失了,所以它的优先级很高。
CPU 理应中断掉正在执行的程序,去做出响应;当 CPU 完成对硬件的响应后,再重新执行用户程序。
中断的过程如下图,它和函数调用差不多,只不过函数调用是事先定好位置,而中断的位置由“信号”决定。
中断程序调用
以键盘为例,当用户按下键盘某个按键时,键盘会给 CPU 的中断引脚发出一个高电平,CPU 能够捕获这个信号,然后执行键盘中断程序。
下图展示了各种硬件通过中断与 CPU 交互的过程:
当网卡把数据写入到内存后,网卡向 CPU 发出一个中断信号,操作系统便能得知有新数据到来,再通过网卡中断程序去处理数据。
epoll的线程安全设计
1.对rbtree–>加锁;
2.对queue -->spinlock
3.epoll_wati,cond,mutex
开源项目中的ET和LT的选择
ET模式
因为ET模式只有从unavailable到available才会触发,所以
读事件:需要使用while循环读取完,一般是读到EAGAIN,也可以读到返回值小于缓冲区大小;
如果应用层读缓冲区满:那就需要应用层自行标记,解决OS不再通知可读的问题
写事件:需要使用while循环写到EAGAIN,也可以写到返回值小于缓冲区大小
如果应用层写缓冲区空(无内容可写):那就需要应用层自行标记,解决OS不再通知可写的问题。