在文章《unix网络编程》(12)五种I/O模型中提到了五种I/O模型,其中前四种:阻塞模型、非阻塞模型、信号驱动模型、I/O复用模型都是同步模型;还有一种是异步模型。html
想写一个系列的文章,介绍从I/O多路复用到异步编程和RPC框架,整个演进过程,这一系列可能包括:linux
多路复用技术要解决的是“通讯”问题,解决核心在于“同步事件分离器”(de-multiplexer),linux系统带有的分离器select、poll、epoll网上介绍的比较多,你们能够看看这篇介绍的不错的文章:我读过的最好的epoll讲解。通讯的一方想要知道另外一方的状态(以决定本身作什么),有两种方法: 一是轮询,二是消息通知。程序员
轮询的一种典型的实现多是这样的:固然这里的epoll_wait()也可使用poll()或者select()替换。算法
while (true) { active_stream[] = epoll_wait(epollfd) for i in active_stream[] { read or write till } }
轮询方式主要存在如下不足:编程
其实现方式一般是: "阻塞-通知"机制。阻塞会致使一个任务(task_struct,进程或者线程)只能处理一个"I/O流"或者相似的操做,要处理多个,就要多个任务(须要多个进程或线程),所以灵活性上又不如轮询(一个任务足够),很矛盾。小程序
select、poll、epoll对比数组
矛盾的根源就是"一"和"多"的矛盾: 但愿一个任务处理多个对象,同时避免处理阻塞-通知机制的内部细节。解决方案是多路复用(muliplex)。多路复用有3种基本方案,select()/poll()/epoll(),都是来解决这一矛盾的。服务器
那么上面3个系统调用的区别是什么呢?
第一个select(),结合了轮询和阻塞两种方式,没有问题,每次有一个对象事件发生的时候,select()只是知道有事件发生了,具体是哪一个对象发生的,不知道,须要从头至尾轮询一遍,复杂度是O(n)。poll函数相对select函数变化不大,只是提高了最大的可轮询的对象个数。epoll函数把时间复杂度降到O(1)。网络
为何select慢而epoll效率高?
select()之因此慢,有几个缘由: select()的参数是一个FD数组,意味着每次select调用,都是一次新的注册-阻塞-回调,每次select都要把一个数组从用户空间拷贝到内核空间,内核检测到某个对象状态变化并写入后,再从内核空间拷贝回用户空间,select再把这个数组读取一遍,并返回。这个过程很是低效。并发
epoll的解决方案至关因而一种对select()的算法优化: 它把select()一个函数作的事情分解成了3步,首先epoll_create()建立一个epollfd对象(至关于一个池子),而后全部被监听的fd经过epoll_ctrl()注册到这个池子,也就是为每一个fd指定了一个内部的回调函数(这样,就没有了每次调用时的来回拷贝,用户空间的数组到内核空间只有这一次拷贝)。epoll_wait阻塞等待。在内核态有一个和epoll_wait对应的函数调用,把就绪的fd,填入到一个就绪列表中,而epoll_wait读取这个就绪列表,作到了快速返回(O(1))。
详细的对比能够参考select、poll、epoll之间的区别总结:https://www.cnblogs.com/Anker/p/3265058.html?spm=ata.13261165.0.0.4ec468f3ruw05F
有了上面的原理介绍,这里举例来讲明下epoll究竟是怎么使用的,加深理解。举两个例子:
一个是比较简单的父子进程通讯的例子,单个小程序,不须要跑多个应用实例,不须要用户输入。http://www.javashuo.com/article/p-oeqeitsy-cw.html
一个是比较实战的socket+epoll,毕竟现实案例中哪有两个父子进程间通信这么简单的应用场景。
有了I/O复用,有了epoll已经可使服务器并发几十万链接的同时,维持高TPS了,难道这还不够吗?答案是,技术层面足够了,但在软件工程层面倒是不够的。例如,总要有个for循环去调用epoll,总来处理epoll的返回,这是每次都要重复的工做。for循环体里面写什么----通知返回以后,作事情的程序最好能以一种回调的机制,提供一个编程框架,让程序更有结构一些。另外一方面,若是但愿每一个事件通知以后,作的事情能有机会被代理到某个线程里面去单独运行,而线程完成的状态又能通知回主任务,那么"异步"的进制就必须被引入。
因此,还有两个问题要解决,一是"编程框架",一是"异步"。咱们先看几个目前流行的框架,大部分框架已经包含了某种异步的机制。咱们接下来的篇章将介绍“编程框架”和“异步I/O模型”。