IO模型之IO多路复用

    服务器端编程一般处理三个问题:网络IO、业务逻辑处理和数据存储。个人感觉网络IO的设计与实现最能体现一个后台工作者的编程功底。当然,目前流行的第三方库如Libevent、Libev、Muduo等都已经很好的解决了这个问题,此处,仅仅是自己把平时自己看到的一些关于网络IO的知识做个记录。

    目前典型的IO模型对比如下:

I/O模型读写操作和阻塞阶段
阻塞IO程序阻塞于读写函数
I/O复用程序阻塞于I/O复用系统调用,但可同时监听多个I/O事件。对IO操作本身是非阻塞的。
SIGIO信号信号触发读写就绪事件,用户程序执行读写操作,程序没有阻塞阶段。
异步IO内核执行读写操作并触发读写完成事件,程序没有阻塞阶段。
阻塞式I/O和I/O多路复用是目前服务端应用程序中最为常见的两种IO模型,两者中IO多路复用技术使用较为广泛。

基本概念:

IO多路复用指的是内核一旦发现进程指定的一个或多个IO条件准备就绪,就通知该线程。

适用场景:

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

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

(3)如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。(accept新客户端与已连接客户端的读写事件)

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

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

优势:

 与多进程或多线程模式相比,IO多路复用最大的特点就是减少系统开销(无论进程池、线程池中CPU的切换还是创建进程或者线程的开销)。

系统API:

目前,IO多路复用系统调用一般有三种:select、poll、epoll,三者的特点对比如下:

selectselect本质是通过设置或者检查存放fd标志位的数据结构来进一步处理。其缺点如下:
1.单个进程可监听的fd数量受限制。
2.需要维护一个用来存放大量fd的数据结构,这样就会使得用户空间和内核空间在传递该结构时复制开销大。
3.对socket扫描时是线性扫描。
pollpoll本质上和select没有区别,它将用户传入的数据拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪,则在设备等待队列中加入一项并继续遍历,如果遍历玩完所有fd后没有发现设备就绪,则挂起当前进程,知道设备就绪或者主动超时,被唤醒后又要再次遍历fd。
1.poll没有最大连接数的限制,原因是poll是使用链表存储内部结构的。
2.大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这种复制是不是有意义的。
3.如果报告了这个fd后没有被处理,那么下次poll时会再次报告该fd(水平触发LT)。
epollepoll支持水平触发(LT)和边沿触发(ET),最大的特点在于边沿触发,它只告诉进程那些fd刚刚变为就绪态,并只会通知一次。
1.epoll使用mmap复制,减少内核和用户件数据交换开销。
2.epoll使用“事件”就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调方式来激活该fd,epoll_wait便可以收到通知。
综上,在选择select,poll,epoll时要根据具体的使用场合以及这三种方式的自身特点。表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。

如果连接数量少且都十分活跃,则select/poll性能要好于epoll。

如果连接数量非常多,但是活跃连接数量较少,则epoll性能要好于select/poll。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值