您的位置:首页 > 其它

I/O多路转接select/poll/epoll的对比

2017-07-01 18:45 211 查看
【I/O复用模型】

〈原理〉

        I/O复用是让应用程序可以同时对多个I/O端口进行监控以判断其上的操作是否可以进行,达到时间复用的目的。举例而言,如果用监控来自10根不同地方的水管(I/O端口)是否有水流到达(即是否可读),那么需要10个人(即10个线程或10处代码)来做这件事。如果利用某种技术(比如摄像头)把这10根水管的状态情况统一传达到某一点,那么就只需要1个人在那个点进行监控就行了,而类似与select或epoll这样的多路I/O复用机制就好比是摄像头的功能,它们能够把多个I/O端口的状况反馈到同一处,比如某个特定的文件描述符上,这样应用程序只需利用对应的select()、poll()或epoll()系统调用阻塞关注这一处即可。具体的select、poll、epoll模型在后面讲。

〈优点〉

       相比多进程多线程服务器,由于I/O多路复用是在单一进程的上下文中的,因此每个逻辑流程都能访问该进程的全部地址空间,所以开销比多进程低得多;

〈缺点〉

       因为它的开销小,必然在编程方面就会麻烦一点。

【多进程模型】

〈原理〉

        构造并发最简单的就是使用多进程,像fork函数。例如,一个并发服务器,在父进程中接受客户端连接请求,然后创建一个新的子进程来为每个新客户端提供服务。

〈优点〉

①每个进程互相独立,即使子进程崩溃也不影响主程序的稳定性;

②通过增加CPU就可以很容易地扩充性能;

③可以尽量减少线程加锁/解锁的影响来提高性能;

④每个子进程都有2GB地址空间和相关资源,因此总体能够达到的性能上限非常大。
〈缺点〉

①逻辑控制复杂,需要和主程序交互; 

②需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算 

③多进程调度开销比较大。

【多线程模型】

〈原理〉

       线程和进程的执行模型有些相似,每个进程的声明周期都是一个线程,我们称之为主线程。线程是对等的,主线程跟其他线程的区别就是它先执行。

〈优点〉

①无需跨进程边界; 

②程序逻辑和控制方式简单; 

③所有线程可以直接共享内存和变量等; 

④线程方式消耗的总资源比进程方式好; 
〈缺点〉

①每个线程与主程序共用地址空间,受限于2GB地址空间; 

②线程之间的同步和加锁控制比较麻烦; 

③一个线程的崩溃可能影响到整个程序的稳定性; 

④到达一定的线程数程度后,即使再增加CPU也无法提高性能了。

【I/O多路转接select】

〈select〉

       select允许进程指示内核等待多个事件中的任何一个发送,并只在有一个或多个事件发生或经历一段指定的时间后才唤醒。

       select系统调用让程序监视多个文件句柄的状态变化。程序会停在select的地方等待,直到被监视的文件句柄有一个或多个发生了状态改变。

       文件句柄实际上是一个整数,比如0是标准输入,1是标准输出,2是标准错误输出,对应的FILE* 结构的表示就是stdin、stdout、stderr。

〈select的特点〉

       ①select可以监控的文件描述符个数取决与sizeof(fd_set)的值;

       ②在将fd加入select监控集的同时,还需要一个array 来保存放到select监控集中的fd,原因是 a)用于在select返回后,array作为源数据和fd_set进行FD_ISSET判断;b)select返回后会把以前加入的但并没有事件发生的fd移除,因此每次开始select前都要重新从array取得fd并逐一加入到array中;
       综上所述,select模型必须在select之前将fd加入到array中,select返回后再循环array判断是否有时间发生。

〈缺点〉

       ①每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大;

       ②同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大;

       ③select支持的文件描述符数量小,默认是1024。 

〈select服务器〉

        待更新

【poll】

〈原理〉

       poll使用一个 pollfd的指针实现。pollfd结构包含了要监视的event和发生的event,不再使用select“参数-值”传递的方式,并且pollfd没有最大数量限制。和select函数一样,poll返 回后,需要轮询pollfd来获取就绪的描述符。 

〈缺点〉

       虽然pollfd没有最大数量限制,但是事实上,随着监视的描述符数量的增长,其效率也会线性下降。 

〈poll服务器〉

        待更新

【epoll】

〈原理〉

       epoll是为处理⼤大批量句柄而作了改进的poll。epoll同样只告知那些就绪的文件描述符,而且当我们调用epoll_wait()获得就绪文件描述符时, 返回的不是实际的描述符,而是一个代表就绪描述符数量的值,你只需要去epoll指定的一 个数组中依次取得相应数量的文件描述符即可,这里使用了内存映射技术,这样便彻底省掉了这些⽂文件描述符在系统调用时复制的开销。

〈优点〉

       ①支持一个进程打开大数目的socket描述符。epoll没有这个限制,它所支持的FD上限是最大可以打开文件的 数目,这个数字一般远大于2048;

       ②IO效率不随FD数目增加而线性下降。epoll不需要像select/poll一样每次调用都会线性扫描全部的集合,
导致效率呈现线性下降。它只会对"活跃"的socket进行操作,这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的;

       ③使用了mmap加速内核与用户空间的消息传递。无论是select、poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。

〈epoll服务器〉

       待更新

       

       
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: