0
点赞
收藏
分享

微信扫一扫

零拷贝和多路复用模型~皎月

无聊到学习 2022-03-12 阅读 61
linux网络

零拷贝和多路复用模型

1.零拷贝

1.1 零拷贝简介

​ 零拷贝指的是从一个存储区域到另一个存储区域的 copy 任务没有 CPU 参与.

​ 通常用于网络文件传输, 以减少 CPU 消耗内存带宽占用, 减少 用户空间CPU 内核空间 的拷贝过程, 减少 用户上下文CPU 内核上下文间的切换, 提高系统效率.

​ 零拷贝需要 DMA 控制器 的协助. Direct Memory Access, 直接内存存取, 是 CPU 的组成部分, 其可以在 CPU 内核 (算术逻辑运算器 ALU 等) 不参与运算的情况下将数据从一个地址空间拷贝到另一个地址空间.

1.2 传统拷贝

场景 将一个硬盘中的文件通过网络发送出去

​ 4 次用户空间与内核空间的上下文切换,以及 4 次数据拷贝

存在问题

​ 应用程序的作用仅仅就是一个数据传输的中介, 最后将 kernel buffer 中的数据传递到了 socket buffer

1.3 零拷贝实现

​ 通过 sendfile 系统调用实现的

kernel buffersocket buffer 有什么区别呢?DMA 控制器所控制的拷贝过程有一个要求,数据在源头的存放地址空间必须连续的. kernel buffer 中的数据无法保证其连续性, 所以需要将数据再拷贝到 socket buffersocket buffer 可以保证了数据的连续性

1.4 Gather Copy DMA

​ 只是将 kernel buffer 中的 数据描述信息 写到了socket buffer 中. 数据描述信息包含了两方面的信息: kernel buffer数据的地址偏移量

​ 传统拷贝中 user buffer 中存有数据, 因此应用程序能够对数据进行修改等操作; 零拷贝中的 user buffer 中没有了数据, 所以应用程序无法对数据进行操作了. Linux 的 mmap 零拷贝解决了这个问题

1.5 mmap 零拷贝

​ 应用程序与内核共享了 Kernel buffer.由于是共享, 所以应用程序也就可以操作该buffer

应用程序可以对数据进行修改

1.6 零拷贝的运用

在主流的开源框架中, 源码层次都会有涉及零拷贝的运用, 消息中间件Kafka在处理文件 I/O以及Netty,

2. 多路复用 select | poll | epoll

复用方式selectpollepoll
操作方式遍历遍历回调
底层实现数组链表哈希表
IO效率每次调用线性遍历,
时间复杂度O(n)
每次调用线性遍历,
时间复杂度O(n)
时间通知方式, 当fd就绪,
系统注册的回调函数就会调用,
将就绪fd放到readList 里, 时间复杂度O(1)
最大连接数1024 (x86)
2048 (x64)
无上限无上限
fd拷贝形式每调select, 需要将fd集合
从用户态拷贝到内核态
每调poll, 需要将fd集合
从用户态拷贝到内核态
调用 epoll_ctl时拷贝进内核并保存,
之后每次epoll_wait不拷贝

2.1 介绍

多进程/多线程连接处理模型

​ 一个用户连接请求会由一个 内核进程 处理, 而一个内核进程会创建一个 应用程序进程

BIO方式: 应用程序进程在未获取到 IO 响应 之前是处于 阻塞态

​ 内核进程不存在对app进程的竞争,一个内核进程对应一个app进程

多路复用连接处理模型

​ 只有一个 app 进程来处理内核进程事务, 且 app 进程一次只能处理一个内核进程事务, 存在竞争

​ 需要通过 “多路复用器” 来获取各个内核进程的状态信息, app 进程在进行 IO 时, 其采用的是 NIO 通讯方式, 即该 app 进程不会阻塞

2.2 实现原理

select

​ 采用 轮询 的方式, 一直在轮询所有的相关内核进程状态. 若已经就绪, 则马上将该内核进程放入到就绪队列. 处理内核事务前, 会从内核空间中将用户连接请求相关数据复制到用户空间

存在的问题

​ 对所有内核进程采用轮询方式效率会很低

​ 由于就绪队列底层由数组实现, 其所能处理的内核进程数量是有限制的, 能够处理的最大并发连接数量是有限制的

​ 从内核空间到用户空间的复制, 系统开销大

poll

​ 由于其就绪队列由链表实现,对于要处理的内核进程数量理论上是没有限制的 ulimit -n

epoll

​ 采用回调方式实现对内核进程状态的获取: 一旦内核进程就绪, 其就会 回调 epoll多路复用器, 进入到多路复用器的 就绪链表队列

​ 应用程序所使用的数据, 使用 mmap 零拷贝机制

​ 内核进程就绪信息通知了 epoll 多路复用器后, 多路复用器就会马上对其进行处理

LT 模式

LT, 水平触发模式. 内核进程的就绪通知由于某种原因暂时没有被 epoll 处理, 则该内核进程就会 定时 将其就绪信息通知 epoll. 直到 epoll 将其写入到就绪队列, 或由于某种原因该内核进程又不再就绪而不再通知. 支持两种通讯方式:BIONIO

ET 模式

ET, 边缘触发模式. 仅支持 NIO 的通讯方式. 当内核进程的就绪信息 仅会通知一次 epoll,无论 epoll 是否处理该通知. 效率要高于 LT 模式, 但其有可能会出现就绪通知被忽视的情况, 即连接请求丢失的情况.

什么时候文件描述符活跃,活跃后内核如何处理

​ epoll工作在ET模式的时候,必须使用非阻塞套文件读写,以避免由于一个文件句柄的阻塞读/阻塞写操作容易阻塞在read函数时,因为没有读取到需要的字节数,而服务器又不能脱离read的阻塞状态去调用epoll函数接收客户端的数据造成死锁。

​ 包从硬件网卡(NIC) 上进来之后,会触发一个中断,告诉 cpu 网卡上有包过来了,需要处理,同时通过 DMA(direct memory access) 的方式把包存放到内存的某个地方,这块内存通常称为 ring buffer,是网卡驱动程序初始化时候分配的

​ 当 cpu 收到这个中断后,会调用中断处理程序,这里的中断处理程序就是网卡驱动程序,因为网络硬件设备网卡需要驱动才能工作。网卡驱动会先关闭网卡上的中断请求,表示已经知晓网卡上有包进来的事情,同时也避免在处理过程中网卡再次触发中断,干扰或者降低处理性能。驱动程序启动软中断,继续处理数据包.

Reference

  • Zero Copy
  • epoll
举报

相关推荐

0 条评论