彻底理解 IO 多路复用实现机制

什么是多路复用

IO 多路复用中多路是指网络连接,复用指的是同一个线程,可以理解为一个线程管理多个连接,是一种同步IO模型,实现一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪就会阻塞应用程序,交出CPU。这种机制的使用需要额外的功能来配合: select、poll、epoll。

为什么需要多路复用

多路复用还是提高效率,节省时间,怎么节约时间呢?在多路复用之前,我们看下网络模型是怎么样的?基于这张神图:
在这里插入图片描述
这是阻塞IO 模型(Blocking IO ),应用跟操作系统交互 请求读取数据,这个时候操作系统要开始读取数据,一直到数据先加载到kernel buff中,然后从kernel复制到user空间,这样应用系统就读取到了。这全程都是一个线程处理,并且应用也一直在等待,那如果一个应用要读取多个数据呢?那就一个一个排队,不是并发的操作。

那肯定就有人说了,能不能快点?能不能不阻塞,于是就有了Non-Blocking IO ,看看图:
在这里插入图片描述
这里就是应用不停的去请求内核,数据准备好了没,不停的请求,数据准备好了就return OK,这样不会被阻塞,但会不停的请求,消耗cpu。那就有没有系统来通知我数据准备好了,这样我就不需要每次请求内核,于是就有了多路复用(IO Multiplexing ),看看图:
在这里插入图片描述
这样就可以不用每次都请求数据了,但要请求2次才能拿到数据,不过另一个好处就是可以多次select请求,然后那个请求数据好了,就recvfrom 处理数据,不过这里可以看到第一个wait for data 是非阻塞的,不用占用应用,但第二个 copy 到 user 是需要阻塞的,总体来说虽然没有节约系统准备数据的时间,但多路复用可以复用一个线程来发送select请求,多个线程来处理已经就绪的数据,将请求和接受数据形成两个操作,并且解耦。附属上总的IO模型的概念图:
在这里插入图片描述

多路复用机制

多路复用的实现主要是利用单线程采用select\poll\epoll等等系统调用获取 fd 列表,遍历有事件的 fd 进行 accept/recv/send ,使其能支持更多的并发连接请求。其中select、poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写FD,读写过程是阻塞的,这三种方法区别获取fd的方式上。

前提知识:文件描述符FD

文件描述符(File descriptor)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

select缺点

select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:

  • 单个进程所打开的FD是有限制的,通过 FD_SETSIZE 设置,默认1024 ;

  • 每次调用 select,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大;
    需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大

  • 对 socket 扫描时是线性扫描,采用轮询的方法,效率较低(高并发)
    当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是epoll与kqueue做的。

poll缺点

poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的,它没有最大连接数的限制,原因是它是基于链表来存储的,但是同样有缺点:

  • 每次调用 poll ,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大;
  • 对 socket 扫描是线性扫描,采用轮询的方法,效率较低(高并发时)

epoll缺点

epoll可以理解为event poll,不同于忙轮询和无差别轮询,epoll会把哪个流发生了怎样的I/O事件通知我们。所以我们说epoll实际上是**事件驱动(每个事件关联上fd)的,此时我们对这些流的操作都是有意义的。
epoll的优点:

  • 没有最大并发连接的限制,能打开的FD的上限远大于1024(1G的内存上能监听约10万个端口);
    效率提升,不是轮询的方式,不会随着FD数目的增加效率下降。只有活跃可用的FD才会调用callback函数;即- Epoll最大的优点就在于它只管你“活跃”的连接,而跟连接总数无关,因此在实际的网络环境中,Epoll的效率就会远远高于select和poll;
  • 内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。

epoll缺点:

  • epoll只能工作在 linux 下

参考博客

彻底理解 IO 多路复用实现机制
Linux 网络编程的5种IO模型:多路复用(select/poll/epoll)
知乎:怎么理解多路复用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值