PHP FPM源代码反刍品味之二:IO多路复用

基础:操作系统IO多路复用机制。

IO多路复用机制,常见的实现方法有select,poll,epoll,kqueue.
IO多路复用是服务器程序开发的核心,也是研究服务器程序源代码的基础。
这里做个简单的介绍。

这里试图用非程序的方式来说明这个机制。

举个例子:

办公室有3个可加热饮料机,分别提供橙汁,茶水,豆浆。
饮料机有一个指示灯,红色表示正在加热,绿色表示完成加热。
有3个水壶用于装热饮,这里假设,水壶容量很大,饮料机要多次加热才能装满一壶。
会议室要开会,任务:接满3水壶加热完成的饮料到会议室备用。

问题:怎么接满三水壶热饮?

(这个问题也太简单了吧,有必要讨论吗?)

办法一
先拿个一水壶接橙汁,指示灯为红色时等待,绿色时接,饮料机多次加热,多次等待,等接满一壶后,在同样的一次接满茶水,豆浆。
这个办法很简单,只需依次等待。
当我们会发现,在等待橙汁加热的时候,茶水和豆浆可能已经加热就绪了。

于是我们改进了这个办法。

办法二
同时监控3个饮料机的指示灯,哪个灯变绿,就去接哪个。
这样效率提高了很多。

细节上看,办法一很简单,只需依次操作。
办法二,减少了等待时间,多了一个监控工作。

这里还有个饮料机列表的概念,和饮料机添加,移除操作。
即需要哪些饮料机,和需求变动的操作。
以上例子,我们需求是橙汁,茶水和豆浆,如果需求变动,需要加入牛奶或者不需要豆浆。
办法一和办法二的饮料机列表要做调整,这一点两者是类似的。

但是办法二也有不足的地方:需要时时查看指示灯的状态。
只有3个饮料机的情况,不易察觉这个过程,试想如果有1000个饮料机,我们要挨个查看这1000个指示灯。

于是我们改进了这个方法。

办法三
每个饮料机加个声音提示功能,即加热完成后声音提醒一下。
这样的好处是在多个饮料机的情况下,我们不用时时检查每个指示灯的状态。
从主动检查变成被动提醒的改进,大大提高了效率。这就是传说中的基于事件的IO多路复用机制
现在我们感觉良好了,当还有改进的地方,

试想下,如果天气寒冷,电力不足,饮料加热很慢。
即使我们同时监控3个饮料机,也会等待很久,即长时间没有任何一个加热就绪的信号。
同时我们还有其他任务,诸如打印报表,准备投影仪等。

聪明的人变想到,不能这样一直等下去,等一会儿,饮料机没动静,就去做其他事,其他事做好了,再过来接饮料。
这里引入了一个超时的概念,即一次等待最长的时间。(当然,可以设定不超时)

加入了超时支持,办法三的效率就更高了,这也是现在多数服务器程序的机制。

整个举例中有个隐含的要求就是,一个水壶不能同时装两种饮料。
即一个水壶一次只能装同一种饮料,橙汁和茶水不能混在一起。
这话似乎有些多余,橙汁和茶水混在一起是很显然的错误。

对于程序开发,这个错误却很容易发生 .
所以这里做个提醒: 橙汁和茶水必要混在一起,味道不好。

以上为日常例子,现在回到技术:
一个饮水机的水龙头相当于一个输入的文件句柄(fd),
指示灯变绿,句柄可读信号。
水壶表示缓冲(BUFFER)
这个例子以输出为例,输入的情况类似。

办法二对应与select方法,也可以加入超时设置。这个方法因为效率不高,已被epoll或kqueue取代,
一些开源软件在windows下面使用这个方法。
办法三对应于epoll,kqueue方法,因为高效,分别在Linux和FreeBSD平台广泛使用。

你可能感兴趣的:(PHP FPM源代码反刍品味之二:IO多路复用)