Linux系统中有一个核心武器:EPOLL池,通常以高并发和高通量IO系统看到。
核心是Goroutine,这是So -called Coroutine。Coroutine的最佳实现是长代码与同步代码相同。例如,在GO中,网络IO似乎是同步的代码。实际上,底部是异步调用。一般过程是:
GO与Coroutine合作,以实现网络上异步过程的同步代码。核心是使用Epoll池来管理网络FD。
在实施方面,背景程序只需要一个来管理多个FD手柄,并响应所有业务方的IO请求。我们称为IO Multi -Way Reuse。
Multi -way指的是多个商业方((处理)接收IO。
转载是指“重复使用此背景处理程序”。
从IO系统的设计师的角度来看,我们不能提及业务党,因为业务是上帝,只有在您服从时,他们需要创建多个FD,那么您需要负责处理这些FD的处理,并且最好必须拥有它。
业务团队无法提出请求,因此您只能询问背景循环程序!
需要什么?快速!快速!这是核心要求。处理必须很快。每个FD频道的最快感觉都必须给予,每个FD都必须感觉到您只在跑他的腿。
有人再次问,然后我的io请求(例如写)对应于处理它的线程,以便所有iOS都不是由共同生产的?是的,但是有瓶颈。一旦线程数量更多,性能就会不好。
这里不再比较多线和IO多路重用以实现高并发性之间的差异。有关详细信息,您可以了解高分nginx和redis的秘密。
我不使用任何其他系统调用。我可以实现多路重用吗?
好吧。
而真:
对于每个手柄阵列{
读/写(FD,/ *参数 */)
}
睡眠(1s)很慢。有一个问题。上面的程序可能会卡在第三行中,因此不允许整个系统运行。为什么?
默认情况下,我们不会添加参数的任何句柄来阻止类型。当我们读取数据时,如果数据还不好,我们将需要等待。当我们编写数据时,如果我们还没有准备好,它将被卡住并等待。因此,伪代码的第三行可能会直接卡住,从而导致整个线程无法运行。
例如,现在有三杆11、12,13,现在读写11杆还没有准备好,只要它们被卡住了,但是12和13的两个手柄已经准备就绪。它将被卡在前面在12和13中,后者12或13将无法运行。这不符合我们的期望,因为我们通过IO Multi -Road是公共服务重复使用的循环线程,并且由于FD而无法直接瘫痪。
如何解决这个问题呢?
只需将fd设置为非块模式即可。在这次,如果数据还没有准备就绪,可以使用返回错误,并且不会卡住线程,以便整个系统都可以运行。例如,上面的句柄11还没有准备好,因此不会被阻止,它只会报告一个错误。此错误需要特殊处理,然后循环线程可以继续执行12、13的读写。
以上是最简单的IO多路复制。但是看来我从未在生产环境中看到过这种IO多路重用?为什么?
因为它还不够高。每个周期是规律的,这将导致吞吐量差,因为当发生时,所有FD都可以使用IO数据,但是目前,您可以想象,您可以想象。评估
然后,有些同学必须再次提问,然后在周期中没有,所以您可以及时处理吗?
这是及时的,但是CPU预计将运行。没有添加它,当不需要FD需要处理时,估计CPU将运行至100%。这也是不可接受的。
turbing,如果吞吐量不浪费CPU,该怎么办?
这种情况很难有所作为,只能要求内核提供机制帮助。因为内核可以及时管理这些通知和日程安排。
我们将整理IO Multi -Way Reuse.io Multi -Road Reuse的需求和原理是一个线程处理多个FD模式。我们的需求是:此“ 1”必须尽可能快以避免所有无效的工作。所有时间都应在手柄的IO上使用。一定没有任何旋转。睡眠时间浪费了。
有工具吗?我们在其中放了一篮FD。只要有一个可以读取和写入数据的FD,背景循环线程就必须立即醒来,并且所有马力都可以运行。
您能做到吗?是的,这种需求只能提供内核与您见面的机制。
是的,如果您想实现辛辣的眼睛,例如睡眠,则必须拍摄Linux核心。毕竟,IO的处理是内核的核心。数据不好。
内核一口气提供了三个工具。
为什么有3个?
历史继续改善和发展。
Linux是否还有其他方法可以实现IO Multi -Way重复使用?
它似乎消失了!
这三种类型到底是什么?
这三个可以管理FD可读事件。当所有FD都无法写入和什么都不做时,它们可以阻止线程并切断CPU。当FD有情况时,有必要通过线程唤醒。
这三种方法是Epoll池中最高的效率。为什么效率最高?
实际上,这很简单。我在这里不提。实际上,它不过是Epoll的使用。选择和民意调查或多或少是不必要的副本。盲目猜测(仅在遍历)FD,因此效率自然很低。
例如,与Select和Epoll相比,池管理了1024个手柄。当循环线唤醒时,选择被掩盖了。我不知道IO在这1024 FDS中已经准备好了。如何处理这种情况?您只能穿越这1024 FD,一一一个。工作。
epoll是不同的。从醒来,您可以准确获取Ready FD阵列。您不需要任何测试。您得到的就是处理它。
让我们看一下Epoll池的使用和原理。
EPOLL的使用非常简单,只有以下3个系统调用。
就是这样吗?是的,这很简单。
在Linux下,Epoll被炸毁为由High和IO实施的秘密武器。该原理实际上非常简单:Epoll的实施几乎没有做任何无效的工作。我们从使用的角度逐步分析。
首先,EPOLL的第一步是创建一个池。这是完成的:
原型:
例子:
这个游泳池对我们来说是一个黑匣子。这个黑匣子用于安装FD。我们暂时不会纠缠详细信息。我们有一个,这只能代表这个epoll池。
然后,我们必须将FD放入此Epoll池中,将使用
原型:
例子:
在上面,我们将手柄11放在这个池中。OP()表示操作已增加,修改,删除。事件结构可以指定可以编写监视事件的类型,可以编写。
即使将FD添加到池中,如果修改和删除了FD?如何快速进行时间?
这是您管理FD的数据结构的方式。
最常见的想法是:使用列表,可以吗?它可以起作用,但性能被撤下。列表的结构是管理元素。时间复杂性太高O(n),并且可以一次又一次地找到位置。池越大,性能越慢。
是否有简单有效的数据结构?
是的,红树和黑树。epoll池的Linux内核的内部实现是管理这些注册过程的手柄fd,其结构是红树和黑树的结构。红树是一棵平衡的二进制树,具有时间复杂o(log n)。即使连续添加,删除和修改此池,它也可以保持非常稳定的搜索性能。
现在考虑第二个高效率秘密:如何确保数据准备就绪并立即感觉到?
epoll_ctl将在这里有点涉及。
在这里思考:民意调查的回调是什么?如何设置?
它是什么?
如FD中所述,Linux被设计为文件的体系结构。这不仅是一个演讲,而且可以在任何地方看到。当实施文件系统时,该文件被称为该结构。该结构在此结构中有很多功能,我已经简化了以下内容,如下所示:
您会看到,,,,等。这些都是文件的自定义处理操作。实际上,在此框架中实现了文件的操作。例如,如果定制了ext2,那么它将是,ext4将为。在特定的“文件”中,相应的文件系统将分配给文件结构。
然后,我们很容易知道这是文件系统自定义FD读数的行为调用。
这是实现定制监视事件机制的实现。通过轮询机制,上层可以直接告知底层。一旦我在FD中读写和写入,请自动将与FD相关的结构放在指定的队列中,当调整基础硬件(例如网络卡)并唤醒操作系统时。
例如:实际上留下了网卡接收软件包的异步过程。操作系统将数据投放到指定的位置。网卡继续从该指定地点支付数据。请求响应通过中断恢复来处理。中断通常分为两个部分:硬中断和软中断。轮询功能是为道路上的这种软中断增加一个点。只要触发阅读和写作事件,它将立即通知上层。此事件通知的形式可以完全消失浪费时间窗口。
重点:这种民意调查事件回调机制是Epoll池高效效率的核心原理。
要点:Epoll池管理的句柄只能是支持的文件FD。
第二个问题:如何设置?
在实现实施的过程中,一个步骤是呼叫中将有判断。如果实现了FD所在的文件系统,则您将直接调用它。如果没有,则将报告响应的错误代码。
您必须对民意调查到底打电话感到好奇?
总结:挂钩并设置一个唤醒路径。与底层连接的EPOLL的回调功能是:,此功能实际上非常简单,请执行两件事:
当FD满足可读并可以写入时,它将按一层调整,最后调用此回调功能将相应的FD结构放在准备队列中,以便从Out唤醒Epoll。
这对应的结构是什么?
该结构被调用,并且注册到Epoll池的每个FD将对应于一个。
准备好排队很高吗?
就绪队列很简单,因为无需进行搜索,只要最终准备就绪的排队中的表明,就必须处理并且必须处理。因此,就绪队列是最简单的双点链接列表。
摘要:Epoll是Epoll提高效率的最关键点:
来思考另一个问题:由于并非所有FD相应的文件系统都实现了民意测验接口,因此自然而然地,并非所有FD都可以放入Epoll池中。那么,文件系统的哪些file_operations实现了轮询接口?
首先,未实现常规文件系统,例如Ext2,Ext4和XF。换句话说,这些最常见和真正的文件系统您确实无法使用EPOLL机制。
谁支持?
最常见的是网络套接字:套接字。网络也是Epoll池的最常见应用程序。所有事物都是Linux下的文件,并且插座实现了一组逻辑(net/socket.c):
我们看到插座已实现,因此可以在Epoll池自然管理插座FD。
还有吗?
是的,实际上,Linux下有两个典型的FD,通常放置在Epoll池中。
概括:
实际上,在Linux模块的划分中,EventFD,TimerFD和Epoll池都是文件系统的模块。
早些时候,我们已经考虑了很多知识点,并且有一些简单而有趣的知识点,促使读者和朋友在这里吸引Jade。
问题:单个核心CPU可以并行吗?
不。
问题:单程可以高度同时发生吗?
能。
问题:并发和并行有什么区别?
一个是执行时间段,另一个是时间和时间的执行。
问题:一个线程如何保持高并合并?
io Multi -Road Reuse,今天的Epoll池是有道理的。
问题:单个线程中是否有开源实现的示例?
redis,nginx是非常好的学习示例。当然,我们的golang的运行时实现也是如此。
epoll池非常简单,但并不简单。一直以来,Linux内核为您提供了帮助。
今天,没有实现源代码的实现。它基于一个小思维点。我简短地谈论了某些Epoll的想法。我可以有什么机会分享异步的IO(AIO)和Epoll?Golang如何使用Epoll池?请继续关注。
原件并不容易,更干燥的商品,请关注:Qiyun Cloud Storage