在过去的几年里,我一直在听到IO_调节。它是Linux中相对较新的技术,以允许高性能的IO具有很少的开销。
每当被提及时,它通常被呈现为选择,民意调查和威拓的新替代方案。这让我相信它只是那些设施的下一次迭代,这就是告知一个程序发生在文件或网络套接字或其他内容的程序中的另一个设施,以便它可以采取行动。换句话说,递增的改进,大概是较少的开销,但否则更多的是。哪个很好,但对我来说无聊:我很了解这个概念,但这些天我跑了其他人和#39;软件,并不真正写自己,所以我没有太多关心更精细的细节。
然后上周我正在观看Brendan Gregg的Lisa21谈话“计算性能:在地平线上”,这张滑块引起了我的注意:
我不知道这是“更快的Syscalls”或图表的承诺,但有些东西告诉我,我意识到的是我的意识。我不知道是什么,但我以为我认为我应该尝试一下。
Thinkng它是一种新的描述符读取性设施,我想只是写一个愚蠢的多用户Telnet聊天服务器。这种程序是对我来说的曾经是面包和黄油一次,很久以前 - 写作泥浆聊天服务器是我开始学习C,UNIX和网络编程的地方。事实证明,这还有很久以前,大多数有趣的信息都脱离了我的头脑。
因此,我设计了yoctochat:最简单的聊天服务器的一种形状,每次使用不同的描述符读取性设施多次实现。我开始选择一个,然后是一个投票。 EPOLS版本工具一点时间更长,因为我以前从未使用过,但是因为它更多的是,形状基本相同。
随着那些脱离的人,即使是几天,我甚至是yc_uration.c,即使是那些这些计划的人,也是一个人的统一。几次失败后,我开始感受到事物,它开始形成。后来,我停下来做一些房子琐事,正在考虑我建造的程序的形状,它打了我:
IO_调节根本不是一个事件系统。 io_uring实际上是一般的异步Syscall设施。
Classic UNIX IO SYSCALL(例如,read())都是同步的,阻塞。你称他们为他们,你的程序睡觉,直到你要求的东西发生。在read()的情况下,即“数据到达”。
显而易见的问题是,如果你想一次从多件事中读取(),你会怎么做?如果我们在试图从一件事中读取时阻止怎么办,那么另一件事就会发生一些事情?它可能会永远等待!
有一个尴尬的解决方案,如设置警报以中断操作,以便我们可以移动到下一件事,或使用“非阻塞”模式,但两者都有他们的问题。唯一有效的是使用描述符读取性设施,以便我们可以说“当任何这些东西都有要读取的东西时叫醒我,然后告诉我哪些是”。一旦火灾,我们就会通过它报告的东西,并在每个人上呼叫读(),知道他们不会阻止,因为它们都有等待的东西。
select()是用于描述符准备的原始UNIX工具。它适用于少数人,但不缩放到很远。 poll()是创建的,以解决其中一些问题,而是添加了一些问题。大多数Unixlikes在此之后,最重要的系统,最符合的是Linux的ePoll和FreeBSD的kque,这是多年来延伸的迄今为止的武器。它们都是概念上的与旧方法相同:让系统在任何有趣的事情发生的事情发生时唤醒过程,因此该过程可以去采取行动。
虽然我会采取不同的方法。它往后回来看看新的眼睛原来的问题,并说它是什么,而不是内核告诉我们什么时候准备好采取行动,以便我们可以接受它,我们告诉内核对我们有什么行动想采取,当条件变得正确时它会这样做。
无论如何,这几乎总是我们想要的。在传统的模型中,用户程序调用内核,要求它告诉它,当某些东西已准备就绪时,然后立即调用回内核以使其执行该操作。用户程序之间的任何内容都没有,因此如果可以将这两个调用组合并提交给内核,则用户程序根本不必参与。
它的操作也相当简单。所有它确实都分开了一半的呼叫 - 你提出了一个请求,一段时间后,它完成了,你会得到结果。虽然请求和响应以不同方式进行编码(调用名称和参数在您提交的内存缓冲区中,而不是实际函数调用),但它的效果相同 - 内核被要求代表该程序进行操作。
整件事件适用于一对队列:提交队列,您将请求服务,以及完成队列,您可以在那里找到与其结果完成的请求。
整个“环形缓冲区”和“催促”的东西?他们真的只是实施细节,这可能是这样的方式来解释我的混淆:每个该死的描述都对环形缓冲区感到兴奋,所以我认为它们实际上是它的重要组成部分,当真的感觉更像只是打电话给远程API。
自从另一种做Syscalls的方式,它基本上适用于一切,包括文件IO,传统上是难以异步的。所以它有可能使很多程序更简单。
一旦我想出来,我留下了非常深刻的印象,我很期待在我使用的更多程序中看到它。我只是希望它周围有点更好的文档,因为我想知道还有多少还没有看过它,因为他们认为这是不同的东西?谁知道!