图解I/O中的零拷贝技术
什么是零拷贝?
零拷贝是一种计算机系统中的 I/O 优化技术,它的核心思想是在数据传输过程中尽可能地减少或完全避免 CPU 将数据从一个存储区域复制到另一个存储区域的操作,从而减少了上下文切换和 CPU 拷贝时间,提高了系统的性能和效率。在 Java 领域,诸如 Netty、Kafka、RocketMQ 等框架就使用了零拷贝技术来提高性能和效率,尤其在处理大规模数据传输时表现突出。
什么是 DMA 技术?
直接内存访问(Direct Memory Access) 技术。简单理解就是,在进行 I/O 设备和内存的数据传输的时候,数据搬运的工作全部交给 DMA 控制器,而 CPU 不再参与任何与数据搬运相关的事情,这样 CPU 就可以去处理别的事务。
传统I/O是如何操作的?
read(file, tmp_buf, len);
write(socket, tmp_buf, len);
期间共发生了 4 次用户态与内核态的上下文切换,因为发生了两次系统调用,一次是 read() ,一次是 write(),每次系统调用都得先从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态。
其次,还发生了 4 次数据拷贝,其中两次是 DMA 的拷贝,另外两次则是通过 CPU 拷贝的:
- 第一次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区里,这个拷贝的过程是通过 DMA 搬运的。
- 第二次拷贝,把内核缓冲区的数据拷贝到用户的缓冲区里,于是我们应用程序就可以使用这部分数据了,这个拷贝到过程是由 CPU 完成的。
- 第三次拷贝,把刚才拷贝到用户的缓冲区里的数据,再拷贝到内核的 socket 的缓冲区里,这个过程依然还是由 CPU 搬运的。
- 第四次拷贝,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程又是由 DMA 搬运的。

那零拷贝的方案有哪些呢?
1、Mmap+Write
在前面我们知道,read() 系统调用的过程中会把内核缓冲区的数据拷贝到用户的缓冲区里,于是为了减少这一步开销,我们可以用 mmap() 替换 read() 系统调用函数。
buf = mmap(file, len);
write(sockfd, buf, len);
mmap() 系统调用函数会直接把内核缓冲区里的数据「映射」到用户空间,这样,操作系统内核与用户空间就不需要再进行任何的数据拷贝操作。
具体过程如下:
- 应用进程调用了
mmap()后,DMA 会把磁盘的数据拷贝到内核的缓冲区里。接着,应用进程跟操作系统内核「共享」这个缓冲区; - 应用进程再调用
write(),操作系统直接将内核缓冲区的数据拷贝到 socket 缓冲区中,这一切都发生在内核态,由 CPU 来搬运数据; - 最后,把内核的 socket 缓冲区里的数据,拷贝到网卡的缓冲区里,这个过程是由 DMA 搬运的。

我们可以得知,通过使用 mmap() 来代替 read(), 可以减少一次数据拷贝的过程。
但这还不是最理想的零拷贝,因为仍然需要通过 CPU 把内核缓冲区的数据拷贝到 socket 缓冲区里,而且仍然需要 4 次上下文切换,因为系统调用还是 2 次。
2、SendFile
在 Linux 内核版本 2.1 中,提供了一个专门发送文件的系统调用函数 sendfile(),函数形式如下:
#include <sys/socket.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
它的前两个参数分别是目的端和源端的文件描述符,后面两个参数是源端的偏移量和复制数据的长度,返回值是实际复制数据的长度。
首先,它可以替代前面的 read() 和 write() 这两个系统调用,这样就可以减少一次系统调用,也就减少了 2 次上下文切换的开销。
其次,该系统调用,可以直接把内核缓冲区里的数据拷贝到 socket 缓冲区里,不再拷贝到用户态,这样就只有 2 次上下文切换,和 3 次数据拷贝。如下图:

但是这还不是真正的零拷贝技术,如果网卡支持 SG-DMA(The Scatter-Gather Direct Memory Access)技术(和普通的 DMA 有所不同),我们可以进一步减少通过 CPU 把内核缓冲区里的数据拷贝到 socket 缓冲区的过程。
具体过程如下:
- 第一步,通过 DMA 将磁盘上的数据拷贝到内核缓冲区里;
- 第二步,缓冲区描述符和数据长度传到 socket 缓冲区,这样网卡的 SG-DMA 控制器就可以直接将内核缓存中的数据拷贝到网卡的缓冲区里,此过程不需要将数据从操作系统内核缓冲区拷贝到 socket 缓冲区中,这样就减少了一次数据拷贝;

这就是所谓的零拷贝(Zero-copy)技术,因为我们没有在内存层面去拷贝数据,也就是说全程没有通过 CPU 来搬运数据,所有的数据都是通过 DMA 来进行传输的。
总结:
| I/O操作 | 数据拷贝次数 | 上下文切换次数 |
| 传统I/O | 2次CPU拷贝,2次DMA拷贝 | 4 |
| Mmap+Write | 1次CPU拷贝,2次DMA拷贝 | 4 |
| SendFile | 1次CPU拷贝,2次DMA拷贝 | 2 |
| SendFile + 支持 SG-DMA | 1次DMA拷贝,1次SG-DMA拷贝 | 2 |
零拷贝技术的文件传输方式相比传统文件传输的方式,减少了 2 次上下文切换和数据拷贝次数,只需要 2 次上下文切换和数据拷贝次数,就可以完成文件的传输,而且 2 次的数据拷贝过程,都不需要通过 CPU,2 次都是由 DMA 来搬运。
所以,总体来看,零拷贝技术可以把文件传输的性能提高至少一倍以上。
ps:以下是我整理的java面试资料,感兴趣的可以看看。最后,创作不易,觉得写得不错的可以点点关注!
链接:https://www.yuque.com/u39298356/uu4hxh?# 《Java面试宝典》
相关文章:
图解I/O中的零拷贝技术
什么是零拷贝? 零拷贝是一种计算机系统中的 I/O 优化技术,它的核心思想是在数据传输过程中尽可能地减少或完全避免 CPU 将数据从一个存储区域复制到另一个存储区域的操作,从而减少了上下文切换和 CPU 拷贝时间,提高了系统的性能和…...
【设计模式】Java 设计模式之桥接模式(Bridge)
桥接模式(Bridge Pattern)是结构型设计模式的一种,它主要解决的是抽象部分与实现部分的解耦问题,使得两者可以独立变化。这种类型的设计模式属于结构型模式,因为该模式涉及如何组合接口和它们的实现。将抽象部分与实现…...
记录dockers中Ubuntu安装python3.11
参考: docker-ubuntu 安装python3.8,pip3_dockerfile ubuntu22 python3.8-CSDN博客...
【算法专题--双指针算法】leetcode--283. 移动零、leetcode--1089. 复写零
🍁你好,我是 RO-BERRY 📗 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 🎄感谢你的陪伴与支持 ,故事既有了开头,就要画上一个完美的句号,让我们一起加油 目录 前言1. 移动零࿰…...
【JavaEE -- 多线程3 - 多线程案例】
多线程案例 1.单例模式1.1 饿汉模式的实现方法1.2 懒汉模式的实现方法 2. 阻塞队列2.1 引入生产消费者模型的意义:2.2 阻塞队列put方法和take方法2.3 实现阻塞队列--重点 3.定时器3.1 定时器的使用3.2 实现定时器 4 线程池4.1 线程池的使用4.2 实现一个简单的线程池…...
k8s的pod服务升级,通过部署helm升级
要通过Helm升级Kubernetes(k8s)中的Pod服务,你可以按照以下步骤进行操作: 安装Helm: 如果你还没有安装Helm,可以通过官方文档提供的方式进行安装。添加Helm仓库: 确保你已经添加了包含你要升级…...
复现文件上传漏洞
一、搭建upload-labs环境 将下载好的upload-labs的压缩包,将此压缩包解压到WWW中,并将名称修改为upload,同时也要在upload文件中建立一个upload的文件。 然后在浏览器网址栏输入:127.0.0.1/upload进入靶场。 第一关 选择上传文件…...
Java 内存异常
内存溢出 内存溢出指的是在程序执行过程中,申请的内存超过了系统实际可用的内存资源。 内存溢出的常见情况: 创建大量对象并持有引用:在程序中创建大量对象并持有对这些对象的引用,而没有及时释放这些引用,导致堆内存…...
Windows11去掉 右键菜单的 AMD Software:Adrenalin Edition 选项
Windows11去掉 右键菜单的 AMD Software:Adrenalin Edition 选项 运行regedit打开注册表编辑器 先定位到 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PackagedCom\Package 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\PackagedCom\Package找到 AdvancedMicroDevicesInc-2.…...
uniapp实现我的订单页面无感 - 删除数据
在进入我们的订单页面时进行获取列表,上拉加载,下拉刷新等请求,我们在删除数据时,请求删除接口后,不要重新去请求数据,不要重新去请求数据,不要重新去请求数据 重新请求会刷新页面中的数据 方…...
MySQL—redo log、undo log以及MVCC
MySQL—redo log、undo log以及MVCC 首先回忆一下MySQL事务的四大特性:ACID,即原子性、一致性、隔离性和持久性。其中原子性、一致性、持久性实际上是由InnoDB中的两份日志保证的,一份是redo log日志,一份是undo log日志ÿ…...
13 list的实现
注意 实现仿cplus官网的list类,对部分主要功能实现 实现 文件 #pragma once #include <assert.h>namespace mylist {template <typename T>struct __list_node{__list_node(const T& x T()): _prev(nullptr), _next(nullptr), _data(x){}__lis…...
如何用client-go获取k8s因硬盘容量、cpu、内存、gpu资源不够引起的错误信息?
在Kubernetes中,你可以使用client-go库来获取Pod的状态和事件,这些信息可能包含了由于资源不足引起的错误信息。 以下是一个基本的示例,展示如何使用client-go来获取Pod的状态和事件: package mainimport ("flag"&quo…...
IDEA编译安卓源码TVBox(2)
一、项目结构:主要app和player app结构 二、增加遥控器按键选台 修改LivePlayActivity.java 1、声明变量 public String channelId "";public Timer timer new Timer();public Toast mToast;2、定义方法 private void mToastShow(String s){mToast …...
【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件详细说明
欢迎来到《小5讲堂》 大家好,我是全栈小5。 这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解, 特别是针对知识点的概念进行叙说,大部分文章将会对这些概念进行实际例子验证,以此达到加深对知识点的理解和掌握。…...
第十四届蓝桥杯省赛真题 Java 研究生 组【原卷】
文章目录 发现宝藏【考生须知】试题 A: 特殊日期试题 B: 与或异或试题 C: 棋盘试题 D: 子矩阵试题 E : \mathrm{E}: E: 互质数的个数试题 F: 小蓝的旅行计划试题 G: 奇怪的数试题 H: 太阳试题 I: 高塔试题 J \mathrm{J} J : 反异或 01 串 发现宝藏 前些天发现了一个巨牛的人…...
adb shell input text 输入中文
由于adb 不支持中文输入(不支持 Unicode),需要使用虚拟键盘绕一圈。 可以直接参考和使用: https://github.com/senzhk/ADBKeyBoard # 通用方式 adb shell am broadcast -a ADB_INPUT_TEXT --es msg 赞 # mac/linux 支持 base64…...
Rudolf and the Ball Game
传送门 题意 思路 暴力枚举每一个妆台的转换条件 code #include<iostream> #include<cstdio> #include<stack> #include<vector> #include<algorithm> #include<cmath> #include<queue> #include<cstring> #include<ma…...
计算机毕业设计-基于大数据技术下的高校舆情监测与分析
收藏和点赞,您的关注是我创作的动力 文章目录 概要 一、研究背景与意义1.1背景与意义1.2 研究内容 二、舆情监测与分析的关键技术2.1 robot协议对本设计的影响2.2 爬虫2.2.1 工作原理2.2.2 工作流程2.2.3 抓取策略2.3 scrapy架构2.3.1 scrapy:开源爬虫架…...
WPF使用LiveCharts画图时,横坐标转换成时间
一、背景 使用LiveCharts画图时,横坐标通常为数值类型,要转换成时间等自定义类型,需要用到Formatter进行类型转换。 示例使用MVVM模式编写 二、View代码 关键是设置LabelFormatter属性 <lvc:CartesianChart Series"{Binding Series…...
STM32单片机学习(28) —— STM32的SPI外设
文章目录概述SPI通信的移位机制(以bit为单位)SPI外设框图第一部分:数据通路SPI通信的数据帧格式SPI外设移位机制(以字节为单位)第二部分:主机时钟生成器SPI通信时钟频率与传输速率第三部分:主从…...
光效崩坏?噪点泛滥?色温漂移?——Midjourney专业级光效渲染全流程校准协议,含ACEScg色彩空间适配模板
更多请点击: https://kaifayun.com 第一章:光效崩坏、噪点泛滥与色温漂移的系统性归因诊断 图像采集链路中出现的光效崩坏、噪点泛滥与色温漂移并非孤立现象,而是光学设计、传感器响应、ISP管线调度及环境耦合失配共同作用的结果。三者常呈现…...
Airtest Poco实战:5分钟搞定微信小程序自动化测试环境搭建与元素抓取
Airtest Poco实战:5分钟搞定微信小程序自动化测试环境搭建与元素抓取微信小程序作为轻量级应用的代表,已经渗透到电商、社交、工具等各个领域。随着小程序功能的日益复杂,自动化测试成为保障产品质量的重要手段。本文将带你快速搭建微信小程序…...
第三卷第4章:原型模式设计思想
第三卷第4章:原型模式设计思想 目录介绍 01.案例引入与思考 1.1 痛点场景 1.2 它哪里不舒服 1.3 引出本篇主角 02.原型模式介绍 2.1 原型模式由来 2.2 原型模式定义...
Unity iOS构建报错SDK version is 0的根因与精准修复
1. 这个报错不是Unity在“发脾气”,而是工程配置在“装死”刚接手一个老项目,打开Unity编辑器,点Build Settings准备打包iOS,结果弹出一行红字:“SDK version is 0, cannot build”。我第一反应是——这什么鬼…...
超维计算(HDC)原理与ScalableHD架构优化实践
1. 超维计算(HDC)基础解析超维计算(Hyperdimensional Computing, HDC)是一种受大脑信息处理机制启发的计算范式,其核心思想是用高维随机向量(通常称为超向量或HV)来表示和处理信息。与传统神经网…...
告别手动复制!用这个自定义编辑器脚本一键备份/克隆Unity Terrain Data
告别手动复制!用这个自定义编辑器脚本一键备份/克隆Unity Terrain Data在Unity关卡设计和技术美术的工作流中,地形数据的灵活复用往往意味着反复的手动操作——导出高度图、备份材质参数、复制植被分布,每个环节都可能成为效率瓶颈。想象这样…...
如何快速无损转换B站m4s视频:完整工具使用指南
如何快速无损转换B站m4s视频:完整工具使用指南 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾为B站缓存视频无法在其他设备…...
Midjourney V6锐化失控?3步诊断+5组--sref/--stylize协同参数公式,立竿见影修复模糊与锯齿
更多请点击: https://intelliparadigm.com 第一章:Midjourney V6锐化失控的本质归因 Midjourney V6 引入的全新扩散架构与隐式细节增强机制,导致图像生成过程中高频纹理被过度强化,其根本原因并非参数误配,而是模型在…...
3步免费解锁Cursor Pro:告别设备限制,永久享受AI编程助手高级功能
3步免费解锁Cursor Pro:告别设备限制,永久享受AI编程助手高级功能 【免费下载链接】cursor-free-vip [Support 0.45](Multi Language 多语言)自动注册 Cursor Ai ,自动重置机器ID , 免费升级使用Pro 功能: …...
