本文以磁盘IO为例:

首先了解一下IO类型:

    同步和异步:

        理解关键点:同步和异步的着眼点在于被调用者(内核)是否有消息通知机制

    同步:当被调用者发起调用请求,被调用者直接返回最终结果

    异步:当被调用者发起调用请求,被调用者理解返回结果,但不是最终结果,当最终结果准备完毕,被调用者会通知调用者


    阻塞和非阻塞:

        理解关键点:阻塞和非阻塞的着眼点在于调用者发起调用请求等待结果的时候是否会被挂起

   阻塞:调用者发起请求,返回结果之前会被挂起(不可中断睡眠)

   非阻塞:调用者发起请求,返回结果之前不会被挂起



以一次read()操作为例:

  1.调用者发起请求,内核去加载资源到内核空间(第一阶段)

  2.调用者将资源从内核空间复制到其工作的内存地址空间内(第二阶段)


常见的IO模型:

   阻塞IO:调用者发起请求,被挂起,直到最终结果返回,拷贝资源到进程空间仍为阻塞

   非阻塞IO:调用者发起请求,不被挂起,但没有通知机制,处于忙等待状态,需要不断询问。拷贝资源到进程空间仍为阻塞

   复用IO:调用者向select或poll发起请求,被阻塞在select或poll这一层次,但由于select可以接受多个请求,因此实现了多路IO,但两个阶段进程仍被阻塞,只不过阻塞位置改变。select默认最多可以接受1024个请求

    Apache的prefork模型和worker模型是基于IO复用实现

    由于没有通知机制,以上都是同步的   

    事件驱动IO:调用者向内核发起请求,不被阻塞,当资源准备完毕,内核会通知调用者,第二阶段仍为阻塞

    Apache的event模型使用事件驱动IO,Nginx默认也是使用事件驱动IO

    异步IO:两段均为非阻塞,且有消息通知机制

    Nginx支持AIO


复用IO:内核的复用器的实现:select(),poll()

事件驱动IO:内核中驱动器的实现:epoll(),/dev/poll()等


事件驱动中的消息通知机制?

    水平触发:一直通知,直至调用者来取资源

    边缘触发:只通知一次(调用者若在通知时被第二阶段阻塞,之后可以通过回调函数再次调用即可等到结果,nginx默认使用此种机制)