美文网首页
PHP FPM源代码反刍品味之二:IO多路复用

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

作者: 黄洪清 | 来源:发表于2016-07-31 18:17 被阅读372次

    基础:操作系统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多路复用

          本文链接:https://www.haomeiwen.com/subject/ohfxsttx.html