我们需要降低冗余数据拷贝、解放CPU,这也就是零拷贝Zero-Copy技术 。
4.2 解决思路目前来看,零拷贝技术的几个实现手段包括:mmap+write、sendfile、sendfile+DMA收集、splice等 。

文章插图
4.2.1 mmap方式mmap是Linux提供的一种内存映射文件的机制,它实现了将内核中读缓冲区地址与用户空间缓冲区地址进行映射,从而实现内核缓冲区与用户缓冲区的共享 。
这样就减少了一次用户态和内核态的CPU拷贝,但是在内核空间内仍然有一次CPU拷贝 。

文章插图
【一文让你彻底搞清楚,Linux零拷贝技术的那些事儿】mmap对大文件传输有一定优势,但是小文件可能出现碎片,并且在多个进程同时操作文件时可能产生引发coredump的signal 。
4.2.2 sendfile方式mmap+write方式有一定改进,但是由系统调用引起的状态切换并没有减少 。
sendfile系统调用是在 Linux 内核2.1版本中被引入,它建立了两个文件之间的传输通道 。
sendfile方式只使用一个函数就可以完成之前的read+write 和 mmap+write的功能,这样就少了2次状态切换,由于数据不经过用户缓冲区,因此该数据无法被修改 。

文章插图

文章插图
从图中可以看到,应用程序只需要调用sendfile函数即可完成,只有2次状态切换、1次CPU拷贝、2次DMA拷贝 。
但是sendfile在内核缓冲区和socket缓冲区仍然存在一次CPU拷贝,或许这个还可以优化 。
4.2.3 sendfile+DMA收集Linux 2.4 内核对 sendfile 系统调用进行优化,但是需要硬件DMA控制器的配合 。
升级后的sendfile将内核空间缓冲区中对应的数据描述信息(文件描述符、地址偏移量等信息)记录到socket缓冲区中 。
DMA控制器根据socket缓冲区中的地址和偏移量将数据从内核缓冲区拷贝到网卡中,从而省去了内核空间中仅剩1次CPU拷贝 。

文章插图
这种方式有2次状态切换、0次CPU拷贝、2次DMA拷贝,但是仍然无法对数据进行修改,并且需要硬件层面DMA的支持,并且sendfile只能将文件数据拷贝到socket描述符上,有一定的局限性 。
4.2.4 splice方式splice系统调用是Linux 在 2.6 版本引入的,其不需要硬件支持,并且不再限定于socket上,实现两个普通文件之间的数据零拷贝 。

文章插图
splice 系统调用可以在内核缓冲区和socket缓冲区之间建立管道来传输数据,避免了两者之间的 CPU 拷贝操作 。

文章插图
splice也有一些局限,它的两个文件描述符参数中有一个必须是管道设备 。
5.本文小结本文通过介绍数据交互的基本过程、传统模式的缺点,进而介绍了零拷贝的一些实现方法 。
零拷贝技术是非常底层且重要的读写优化,对于服务并发能力的提升有很大帮助,就这么多吧,下期再见!
推荐阅读
- 十个古老而又强大的正则表达式,能让你少写1000行JS代码
- 一文读懂所有HTTP状态码含义
- 个人网站站长的时代要彻底落幕了,挥手不带云彩
- 写不出文章怎么办?学会这个模板让你下笔如有神
- 面膜|面膜哪个牌子好?连明星都爱用的面膜排行榜 用一次就让你入坑
- HDMI和DP区别在哪里?电脑连接线怎么选,一文看懂连接线的历史
- 让你的旧打印机变身WIFI打印机
- 电脑运行缓慢?学会这3招,让你的电脑速度跑起来
- 一文带你理解URI 和 URL 有什么区别?
- Win11彻底解决系统蓝屏问题简单粗暴!只是背景换成了黑屏
