什么是I/O多路复用?

1. 传统的I/O模型

传统的I/O模型是用户态和内核态进行数据通信,用户态向内核态发送询问请求,询问fd中是否有数据,再将内核态的结果返回给用户态。 每发来一个客户端的连接就给其分配一个线程,后续的read/write操作都在对应的线程中进行。 当客户端发来的数量集聚庞大的时候对线程的调度和上下文的切换和调用的内存 就会变得更加繁琐,从而是程序的性能急剧降低。

2. I/O多路复用模型

多路复用:指的是在单个线程中通过记录跟踪每一个I/O流的状态来管理多个I/O流。

简单来说:就是一个进线程可以处理多个文件的I/O。select、poll、epoll是I/O多路复用的三种具体的实现。

2.1 select和poll

Socket 集合通过 select/poll 系统调用从用户态拷贝到内核态,然后由内核检测事件,当有网络事件产生时,内核需要遍历进程关注 Socket 集合,找到对应的 Socket,并设置其状态为可读/可写,然后把整个 Socket 集合从内核态拷贝到用户态,用户态还要继续遍历整个 Socket 集合找到可读/可写的 Socket,然后对其处理。

其实,select 和 poll 并没有本质区别,它们内部都是使用「线性结构」来存储进程关注的 Socket 集合。

2.2 epoll

epoll 在内核里底层是使用红黑树来关注进程所有待检测的 Socket, 通过对这棵红黑树的管理,不需要像 select/poll 在每次操作时都传入整个 Socket 集合,减少了内核和用户空间大量的数据拷贝和内存分配。

epoll 使用事件驱动的机制,内核里维护了一个链表来记录就绪事件,只将有事件发生的 Socket 集合传递给应用程序,不需要像 select/poll 那样轮询扫描整个集合(包含有和无事件的 Socket ),大大提高了检测的效率。

epoll支持边缘触发和水平触发这两种方式,而select/poll只支持水平触发,一般来说,边缘触发的方式比水平触发的效率要高一些。

2.2.1 水平触发(level-trggered)

只要文件描述符(fd)关联的读内核缓冲区为非空,有数据就可以进行读取,就一直发出可读信号进行通知,当文件描述符关联的内核写缓冲区不满,有空间可以写入,就一直发出可写信号进行通知LT模式支持阻塞和非阻塞两种方式。epoll默认的模式是LT(缺省的工作方式,并且同时支持block和no-block socket)。

2.2.2 边缘触发(edge-triggered)

当文件描述符关联的读内核缓冲区由空转化为非空的时候,则发出可读信号进行通知, 当文件描述符关联的内核写缓冲区由满转化为不满的时候,则发出可写信号进行通知 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值