【零拷贝】
目录
一:了解IO基础概念
二:数据流动的层次结构
三:零拷贝
1.传统IO文件读写
2.mmap 零拷贝技术
3.sendFile 零拷贝技术
一:了解IO基础概念
理解CPU拷贝和DMA拷贝
我们知道,操作系统对于内存空间,是分为用户态和内核态的。用户态的应用程序无法直接操作硬件,需要通过内核空间进行操作转换,才能真正操作硬件。这其实是为了保护操作系统的安全。正因为如此,应用程序需要与网卡、磁盘等硬件进行数据交互时,就需要在用户态和内核态之间来回的复制数据。而这些操作,原本都是需要由CPU来进行任务的分配、调度等管理步骤的,早先这些IO接口都是由CPU独立负责,所以当发生大规模的数据读写操作时,CPU的占用率会非常高。

之后,操作系统为了避免CPU完全被各种IO调用给占用,引入了DMA(直接存储器存储)。由DMA来负责这些频繁的IO操作。DMA是一套独立的指令集,不会占用CPU的计算资源。这样,CPU就不需要参与具体的数据复制的工作,只需要管理DMA的权限即可。

DMA拷贝极大的释放了CPU的性能,因此他的拷贝速度会比CPU拷贝要快很多。但是,其实DMA拷贝本身,也在不断优化。
引入DMA拷贝之后,在读写请求的过程中,CPU不再需要参与具体的工作,DMA可以独立完成数据在系统内部的复制。但是,数据复制过程中,依然需要借助数据总进线。当系统内的IO操作过多时,还是会占用过多的数据总线,造成总线冲突,最终还是会影响数据读写性能。
为了避免DMA总线冲突对性能的影响,后来又引入了Channel通道的方式。Channel,是一个完全独立的处理器,专门负责IO操作。既然是处理器,Channel就有自己的IO指令,与CPU无关,他也更适合大型的IO操作,性能更高。

这也解释了,为什么Java应用层与零拷贝相关的操作都是通过Channel的子类实现的。这其实是借鉴了操作系统中的概念。
channel知识点:
在计算机系统中,“通道”(Channel) 的具体作用范围取决于上下文(如硬件架构、操作系统或编程框架)。以下是不同场景下的解释:
通道是 数据传输的路径或抽象机制,通常不直接等同于“操作系统内存 ↔ 外设”的物理传输,而是分层协作中的一环。
(1) 硬件层的通道(如传统大型机)
-
功能:
某些系统(如 IBM 大型机)的 I/O 通道 是专用硬件,直接管理外设(磁盘、磁带)与内存的传输。 -
特点:
-
通道是独立于 CPU 的处理器,可执行复杂的 I/O 指令(如协议解析、数据分块)。
-
直接与外设控制器交互,完成物理数据传输(类似增强版 DMA)。
-
-
示例:
大型机中,通道从磁盘读取数据到内存,无需 CPU 干预。
(2) 操作系统层的通道(如设备驱动)
-
功能:
操作系统通过 设备驱动 和 内核 I/O 子系统 管理外设与内存的交互。 -
特点:
-
通道在此上下文中更接近 逻辑抽象(如
/dev下的设备文件)。 -
实际数据传输依赖 DMA 或 PIO(编程 I/O)。
-
(3) 编程框架中的通道(如 Java NIO)
-
功能:
Java NIO 的Channel(如FileChannel、SocketChannel)是 用户空间与内核空间之间的桥梁。 -
特点:
-
通过系统调用与内核交互,数据在用户缓冲区(如
ByteBuffer)和内核的 Page Cache 之间传输。 -
不直接操作外设,物理传输由操作系统和 DMA 完成。
-
二:数据流动的层次结构
计算机系统中,数据从程序到磁盘(或反向)的流动通常经过以下层级:
程序中的 IO 流 → 用户空间缓冲区 → 操作系统缓存页(内核空间) → 磁盘驱动 → 物理磁盘
示意图
程序代码 用户空间 内核空间 硬件层
┌───────────┐ ┌─────────────┐ ┌──────────────┐ ┌────────┐
│ IO 流 │ → → → │ 用户缓冲区 │ → → → │ Page Cache │ → → → │ 磁盘 │
└───────────┘ └─────────────┘ └──────────────┘ └────────┘(程序层) (操作系统层) (物理层)
而零拷贝技术是减少用户空间和内存空间之间数据传输的次数,接下来,将进入零拷贝的讲解。
三:零拷贝
零拷贝(Zero-copy) 是一种优化技术,旨在 减少或消除数据在内存中的冗余复制操作,从而提升 I/O 性能。它主要作用于 用户空间内存与内核空间内存之间的数据传输,但最终目标是减少整个数据链路(从磁盘到网络、或内存到外设)中的复制次数。
对于Java应用层来说,零拷贝有mmap和sendFile两种方式。
1.传统IO文件读写
说零拷贝技术之前,要先了解传统的IO文件读写是怎么样的,才能更好的理解零拷贝技术,下面先说传统IO的读写工作流程。
传统IO文件读写
传统IO文件读写如下图1-1所示:

图1-1 传统IO文件读写流程图
传统IO文件读写工作流程:
整体流程
Java 程序 → 用户空间 → 内核空间(Page Cache) → 磁盘(修改数据) ↑↓(读写) (DMA 传输)
流程分三个阶段:读取数据 → 修改数据 → 写回数
详细步骤与层级交互
(1) 打开文件
-
Java 代码:使用
FileInputStream、FileChannel或RandomAccessFile打开文件。 -
系统调用:
open(),触发内核创建文件描述符,建立程序与文件的连接。
(2) 读取数据(磁盘 → 内核空间 → 用户空间)
-
磁盘到内核空间(Page Cache):
-
DMA 传输:磁盘控制器通过 DMA(直接内存访问) 将文件数据直接读取到内核的 Page Cache,无需 CPU 参与。
-
触发方式:Java 调用
FileChannel.read(ByteBuffer)或InputStream.read(),底层触发read()系统调用。
-
-
内核空间到用户空间:
-
数据拷贝:内核将 Page Cache 中的数据复制到用户空间的缓冲区(如
byte[]或ByteBuffer)。 -
性能开销:此拷贝由 CPU 完成,是小文件读取的主要性能瓶颈。
-
(3) 修改数据(用户空间内操作)
-
Java 操作:在用户空间的缓冲区中修改数据(如字符串替换、字节操作)。
-
示例:
String content = new String(buffer.array(), StandardCharsets.UTF_8); String modifiedContent = content.replace("old", "new"); byte[] newData = modifiedContent.getBytes(StandardCharsets.UTF_8);
(4) 写回数据(用户空间 → 内核空间 → 磁盘)
-
用户空间到内核空间(Page Cache):
-
数据拷贝:用户空间的修改后数据通过
FileChannel.write(ByteBuffer)或OutputStream.write()触发write()系统调用,将数据复制到内核的 Page Cache。 -
延迟写入:数据暂存于 Page Cache,不会立即写入磁盘。
-
-
内核空间到磁盘:
-
DMA 传输:操作系统通过 DMA 将 Page Cache 中的数据异步写入磁盘。
-
刷盘时机:
-
定时刷盘:由内核线程(如
pdflush)定期将脏页(修改过的数据)写入磁盘。 -
强制刷盘:调用
FileChannel.force(true)触发fsync()系统调用,确保数据持久化。
-
-
(5) 关闭文件
-
Java 代码:调用
close()释放文件描述符。 -
系统调用:
close(),释放内核资源。
2.mmap 零拷贝技术
mmap 零拷贝技术 的核心是通过内存映射文件(Memory-Mapped File)将文件内容直接映射到用户空间的虚拟内存,从而避免传统 I/O 中用户空间与内核空间之间的数据拷贝。
mmap零拷贝技术IO读写
IO文mmap零拷贝技术文件读写如下图1-2所示:

图2-1 mmap零拷贝技术文件读写流程图
mmap零拷贝IO文件读写工作流程:
工作流程概述
磁盘 → Page Cache →(内存映射)→ 用户空间虚拟内存 →(修改数据)→ Page Cache → 磁盘
详细步骤
1. 打开文件并创建内存映射
-
用户空间:
使用FileChannel.map()将文件映射到用户空间的虚拟内存。 -
内核空间:
内核将文件的磁盘块映射到 Page Cache,并建立用户空间虚拟内存与 Page Cache 的映射关系。 -
代码示例:
FileChannel channel = FileChannel.open(Paths.get("file.txt"), StandardOpenOption.READ, StandardOpenOption.WRITE); MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
2. 读取数据
-
用户空间:
用户程序直接通过MappedByteBuffer访问数据,无需显式调用read()。 -
内核空间:
若数据未加载到 Page Cache,触发缺页中断,内核从磁盘读取数据到 Page Cache。 -
零拷贝:
数据直接从 Page Cache 映射到用户空间,无需复制到用户缓冲区。
3. 修改数据
-
用户空间:
用户程序直接修改MappedByteBuffer中的数据。 -
内核空间:
修改后的数据标记为 脏页(Dirty Page),暂存于 Page Cache。
4. 写回磁盘
-
用户空间:
调用buffer.force()强制将脏页刷回磁盘。 -
内核空间:
内核将脏页从 Page Cache 写回磁盘的对应位置。 -
代码示例:
buffer.force(); // 强制刷盘
5. 关闭映射
-
用户空间:
关闭FileChannel,释放映射的内存区域。 -
内核空间:
解除内存映射,释放相关资源。 -
代码示例:
channel.close();
3.sendFile 零拷贝技术
早期的sendFile其实和mmap一样,实现机制还是依靠CPU进行页缓存与socket缓存区之间的数据拷贝,如图3-1所示。

图3-1 早期的sendFile 读写流程图
从Linux内核2.6.33版本开始,引入了对 Scatter-Gather DMA(分散-聚集 DMA) 的支持,优化了实现机制,在拷贝过程中,并不直接拷贝文件的内容,而是只拷贝一个带有文件位置和长度等信息的文件描述符FD,这样子就大大减少了需要传递的数据。而真实的数据内容,会交由DMA控制器,从页缓存中打包异步发送到socket中。如图3-2所示。

图3-2 Linux内核2.6.33 版本 sendFile 读写流程图
注意: sendfile 系统调用 的主要设计目标是 将文件数据高效地发送到网络套接字,因此它 不支持将用户空间的数据直接写入磁盘。
工作流程概述
磁盘 → Page Cache →(sendfile)→ 网卡
详细步骤
1. 打开文件
-
用户空间:
使用FileChannel打开文件。 -
内核空间:
内核将文件的磁盘块映射到 Page Cache。 -
代码示例:
FileChannel fileChannel = new FileInputStream("file.txt").getChannel();
2. 打开网络套接字
-
用户空间:
使用SocketChannel打开网络连接。 -
内核空间:
内核创建 Socket Buffer,用于管理网络数据。 -
代码示例:
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("host", 8080));
3. 使用 sendfile 发送数据
-
用户空间:
调用FileChannel.transferTo(),底层使用sendfile系统调用。 -
内核空间:
数据直接从 Page Cache 通过 DMA 发送到网卡,绕过用户空间。 -
代码示例:
fileChannel.transferTo(0, fileChannel.size(), socketChannel); // 零拷贝发送
4. 关闭资源
-
用户空间:
关闭FileChannel和SocketChannel,释放资源。 -
内核空间:
释放 Page Cache 和 Socket Buffer 资源。 -
代码示例:
fileChannel.close(); socketChannel.close();
相关文章:
【零拷贝】
目录 一:了解IO基础概念 二:数据流动的层次结构 三:零拷贝 1.传统IO文件读写 2.mmap 零拷贝技术 3.sendFile 零拷贝技术 一:了解IO基础概念 理解CPU拷贝和DMA拷贝 我们知道,操作系统对于内存空间&…...
深入解析 C++ 字符串处理:提取和分割的多种方法
在 C 编程中,字符串处理是一个常见的任务,尤其是在需要从字符串中提取特定数据时。本文将详细探讨如何使用 C 标准库中的工具(如 std::istringstream 和 std::string 的成员函数)来提取和分割字符串,并分析不同方法的适…...
计算机组成原理——存储系统(一)
在人生的道路上,成功与失败交织成一幅丰富多彩的画卷。不论我们是面对胜利的喜悦,还是遭遇失败的痛苦,都不能放弃对梦想的追求。正是在这种追求中,我们不断地超越自我,不断地突破自己的极限。只有勇往直前,…...
Jenkins未在第一次登录后设置用户名,第二次登录不进去怎么办?
Jenkins在第一次进行登录的时候,只需要输入Jenkins\secrets\initialAdminPassword中的密码,登录成功后,本次我们没有修改密码,就会导致后面第二次登录,Jenkins需要进行用户名和密码的验证,但是我们根本就没…...
论文和代码解读:RF-Inversion 图像/视频编辑技术
Diffusion Models专栏文章汇总:入门与实战 前言:Rectified Flow的反演和DDIM这些不太一样,上一篇博客中介绍了腾讯提出的一种方法《基于Rectified Flow FLUX的图像编辑方法 RF-Solver》,主要就是用泰勒展开和一阶导数近似来分解反演公式。这篇博客介绍谷歌提出的方法RF-Inv…...
大模型培训讲师老师叶梓分享:DeepSeek多模态大模型janus初探
以下视频内容为叶梓分享DeepSeek多模态大模型janus的部署,并验证其实际效果,包括图生文和文生图两部分。 叶梓老师人工智能培训分享DeepSeek多模态大模型janus初探 DeepSeek 的多模态大模型 Janus 是一款强大的 AI 模型,专注于图像和文本的多…...
2025最新源支付V7全套开源版+Mac云端+五合一云端
2025最新源支付V7全套开源版Mac云端五合一云端 官方1999元, 最新非网上那种功能不全带BUG开源版,可以自己增加授权或二开 拥有卓越的性能和丰富的功能。它采用全新轻量化的界面UI,让您能更方便快捷地解决知识付费和运营赞助的难题 它基于…...
稀疏混合专家架构语言模型(MoE)
注:本文为 “稀疏混合专家架构语言模型(MoE)” 相关文章合辑。 手把手教你,从零开始实现一个稀疏混合专家架构语言模型(MoE) 机器之心 2024年02月11日 12:21 河南 选自huggingface 机器之心编译 机器之心…...
比较热门的嵌入式项目
嵌入式系统在现代科技中应用广泛,以下是一些当前比较热门的嵌入式项目方向及其应用场景: 1. 物联网(IoT) 智能家居:智能灯光、温控器、安防系统。环境监测:空气质量、温湿度、土壤湿度传感器。工业物联网&…...
牛客网 除2!(详解)c++
题目链接:除2! 1.题目解析 1:想让数组所有数之和尽可能小,肯定有个想法,就是我每次选数组中偶数的时候,我必定挑一个最大的,因为我挑一个最大的出来,把它变成一半,这个时…...
被裁与人生的意义--春节随想
还有两个月就要被迫离开工作了十多年的公司了,不过有幸安安稳稳的过了一个春节,很知足! 我是最后一批要离开的,一百多号同事都没“活到”蛇年。看着一批批仁人志士被“秋后斩首”,马上轮到我们十来个,个中滋味很难言清…...
ASP.NET Core 中间件
目录 一、常见的内置中间件 二、自定义中间件 三、中间件的执行顺序 四、其他自动逸中间件案例 1. 身份验证中间件 2、跨域中间件(CORS) ASP.NET Core 中,中间件(Middleware)是处理 HTTP 请求和响应的组件链。你…...
Pyecharts之图表样式深度定制
在数据可视化的世界里,图表的样式定制对于提升数据展示效果和用户体验至关重要。Pyecharts 提供了丰富的样式定制功能,能让我们创建出独具特色的可视化作品。本篇将深入探讨如何使用 Pyecharts 为图表添加线性渐变色、径向渐变色,以及如何添加…...
git笔记-简单入门
git笔记 git是一个分布式版本控制系统,它的优点有哪些呢?分为以下几个部分 与集中式的版本控制系统比起来,不用担心单点故障问题,只需要互相同步一下进度即可。支持离线编辑,每一个人都有一个完整的版本库。跨平台支持…...
Joplin 插件在Vscode中无法显示图片
1.问题 在vscode里面装好joplin插件之后,无法显示图片内容。 粘贴的图片可以再vscode中显示,无法再joplin客户端显示 2.解决方法 这种情况是因为和vscode自带的MD编辑器的预览模式有冲突,或者没用通过专用方式上传图片。 方法一ÿ…...
python学opencv|读取图像(四十七)使用cv2.bitwise_not()函数实现图像按位取反运算
【0】基础定义 按位与运算:两个等长度二进制数上下对齐,全1取1,其余取0。按位或运算:两个等长度二进制数上下对齐,有1取1,其余取0。 按位取反运算:一个二进制数,0变1,1变0。 【1】…...
pandas分组
分组 分组的关键要素是: 分组依据、数据来源、操作及其返回结果。 df.groupby(分组依据)[数据来源].使用操作对学生按照性别统计身高中位数。 print(df.groupby(Gender)[Height].median())上面是一维度进行分组,如果要根据多个维度分组,则…...
爬虫基础(三)Session和Cookie讲解
目录 一、前备知识点 (1)静态网页 (2)动态网页 (3)无状态HTTP 二、Session和Cookie 三、Session 四、Cookie (1)维持过程 (2)结构 正式开始说 Sessi…...
【Super Tilemap Editor使用详解】(十三):快捷键指南(Keyboard Shortcuts)
在使用 Super Tilemap Editor 进行图块地图编辑时,键盘快捷键可以显著提高工作效率。本文将详细介绍常用的快捷键及其功能,帮助你更快地完成图块绘制、翻转、旋转以及工具切换等操作。 一、快捷键文件位置 所有键盘快捷键的定义可以在以下路径找到&…...
【Leetcode 每日一题】119. 杨辉三角 II
问题背景 给定一个非负索引 r o w I n d e x rowIndex rowIndex,返回「杨辉三角」的第 r o w I n d e x rowIndex rowIndex 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 数据约束 0 ≤ r o w I n d e x ≤ 33 0 \le rowIndex \le 33 …...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
