IO模式与IO多路复用

五种IO模式

阻塞IO(blocking IO):进程发送IO请求,进入阻塞态,等待操作系统内核准备。

非阻塞IO(nonblocking IO):进程发送IO请求后如操作系统内核没准备好数据,则先返回给进程一个err消息,进程稍后继续发送请求直到操作系统内核准备好。但是读写阶段进程依然阻塞。

IO多路复用(IO multiplexing):使用select、epoll、poll机制,当用户调用之后,整个进程进入阻塞,同时操作系统内核监视所有IO事件,有IO事件则立即返回。

信号驱动IO(signal driven IO)

异步IO(Asynchronous IO):用户发起IO请求后立即做其他事情,内核完成IO操作之后回向进程发送信号通知IO完成。

 

 

IO多路复用:

Reactor设计模式

事件驱动,有多个输入源,有多个不同的EventHandler(RequestHandler)来处理不同的请求,Initiation Dispatcher用于管理EventHander,EventHandler首先要注册到Initiation Dispatcher中,然后Initiation Dispatcher根据输入的Event分发给注册的EventHandler;然而Initiation Dispatcher并不监听Event的到来,这个工作交给Synchronous Event Demultiplexer来处理。

使用场景:

1)当客户处理多个描述符时(一般是交互式输入和网络套接口),必须使用I/O复用

2)当一个客户同时处理多个套接口时,这种情况是可能的,但很少出现。

3)如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。

4)如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用。

5)如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。

 

 

 

Select:

原理:select 函数监视的文件描述符分3类,分别是writefds、readfds、和exceptfds。调用后select函数会阻塞,直到有描述符就绪(有数据 可读、可写、或者有except),或者超时(timeout指定等待时间,如果立即返回设为null即可),函数返回。当select函数返回后,可以通过遍历fdset,来找到就绪的描述符。

 

缺点:

1、select最大的缺陷就是单个进程所打开的FD是有一定限制的,它由FD_SETSIZE设置,默认值是1024

2、对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低。

3、需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大。

 

poll:

原理:poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,但是基于链表进行存储,没有最大连接的限制

 

缺点:

1)大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。

2)poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

 

epoll:

原理:epoll支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就绪态,并且只会通知一次。还有一个特点是,epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知。

 

优点:

1、没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口)。

2、效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。

3、内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。

LT模式:(水平触发,level triggered)当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用epoll_wait时,会再次响应应用程序并通知此事件。

ET模式:(边缘触发,edge triggered)当epoll_wait检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用epoll_wait时,不会再次响应应用程序并通知此事件。

 

区别:

连接数:

效率:

消息传递方式:

 

 

对比总结:

1、表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。

2、select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善。