【零拷貝】

目錄

一:了解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 下的設備文件)。

    • 實際數據傳輸依賴 DMAPIO(編程 I/O)

(3) 編程框架中的通道(如 Java NIO)

  • 功能
    Java NIO 的 Channel(如 FileChannelSocketChannel)是 用戶空間與內核空間之間的橋梁

  • 特點

    • 通過系統調用與內核交互,數據在用戶緩沖區(如 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 代碼:使用 FileInputStreamFileChannelRandomAccessFile 打開文件。

  • 系統調用open(),觸發內核創建文件描述符,建立程序與文件的連接。

(2) 讀取數據(磁盤 → 內核空間 → 用戶空間)

  1. 磁盤到內核空間(Page Cache)

    • DMA 傳輸:磁盤控制器通過 DMA(直接內存訪問) 將文件數據直接讀取到內核的 Page Cache,無需 CPU 參與。

    • 觸發方式:Java 調用 FileChannel.read(ByteBuffer)InputStream.read(),底層觸發 read() 系統調用。

  2. 內核空間到用戶空間

    • 數據拷貝:內核將 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) 寫回數據(用戶空間 → 內核空間 → 磁盤)

  1. 用戶空間到內核空間(Page Cache)

    • 數據拷貝:用戶空間的修改后數據通過 FileChannel.write(ByteBuffer)OutputStream.write() 觸發 write() 系統調用,將數據復制到內核的 Page Cache。

    • 延遲寫入:數據暫存于 Page Cache,不會立即寫入磁盤。

  2. 內核空間到磁盤

    • 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. 關閉資源

  • 用戶空間
    關閉 FileChannelSocketChannel,釋放資源。

  • 內核空間
    釋放 Page Cache 和 Socket Buffer 資源。

  • 代碼示例

    fileChannel.close();
    socketChannel.close();

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/894608.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/894608.shtml
英文地址,請注明出處:http://en.pswp.cn/news/894608.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

全棧開發:使用.NET Core WebAPI構建前后端分離的核心技巧(一)

目錄 cors解決跨域 依賴注入使用 分層服務注冊 緩存方法使用 內存緩存使用 緩存過期清理 緩存存在問題 分布式的緩存 cors解決跨域 前后端分離已經成為一種越來越流行的架構模式,由于跨域資源共享(cors)是瀏覽器的一種安全機制,它會阻止前端應用…

《Linux服務與安全管理》| 數據庫服務器安裝和配置

《Linux服務與安全管理》| 數據庫服務器安裝和配置 目錄 《Linux服務與安全管理》| 數據庫服務器安裝和配置 任務一: 安裝PostgreSQL數據庫,設置遠程登錄,客戶端可以成功登錄并操作數據庫。 任務二: 安裝MySQL數據庫&#xf…

Linux系統之whereis命令的基本使用

Linux系統之whereis命令的基本使用 一、whereis命令介紹二、whereis命令的使用幫助2.1 whereis命令的幫助信息2.2 whereis命令幫助解釋 三、whereis命令的基本使用3.1 查找命令的位置3.2 僅查找二進制文件3.3 僅查找手冊頁3.4 輸出實際使用的查找路徑3.5 指定自定義搜索路徑 四…

Autosar-以太網是怎么運行的?(Davinci配置部分)

寫在前面: 入行一段時間了,基于個人理解整理一些東西,如有錯誤,歡迎各位大佬評論區指正!!! 目錄 1.Autosar ETH通訊軟件架構 2.Ethernet MCAL配置 2.1配置對應Pin屬性 2.2配置TXD引腳 2.3配…

2024年度總結

首先,我是在2023年結束高中生涯進入大學的,難免會有固化的“高中生”思維,我等著老師的安排,看著課表上課,跟著時間吃飯,睡覺,偶爾會熬夜,但整體跟高中沒差太多。我對社團沒興趣&…

【Block總結】CSAM,包含分割、關鍵點、切分等均適用!|即插即用

論文信息 標題: CSAM: A 2.5D Cross-Slice Attention Module for Anisotropic Volumetric Medical Image Segmentation 論文鏈接: https://arxiv.org/pdf/2311.04942 GitHub鏈接: https://github.com/aL3x-O-o-Hung/CSAM 創新點 CSAM(跨切片注意力模塊&#xff…

解決PyG安裝中torch-sparse安裝失敗問題:詳細指南

1 問題描述 最近在學習GNN,需要使用PyTorch Geometric(PyG)庫。在安裝PyG的過程中,遇到了torch-sparse安裝失敗的問題,錯誤提示為: ERROR: Failed building wheel for torch-sparse本文將詳細記錄問題的解…

鳥哥Linux私房菜筆記(三)

鳥哥Linux私房菜筆記(三) 該第三部分和第四部分主要為原書的第十一章(正則表達式與文件格式化處理),第十二章學習shell腳本,第十六章(進程管理與SElinux初探部分),第十七…

學習日記-250203

一.論文 看師兄寫好的一稿。 二、計劃: 繼續看論文里的問題。 然后繼續看promptCD相關,明天要看論文啦,今天家里有些事比較忙(碎碎念) 三. )——( 注冊了 openreview,ORCID,Google scholar&…

python學opencv|讀取圖像(五十四)使用cv2.blur()函數實現圖像像素均值處理

【1】引言 前序學習進程中,對圖像的操作均基于各個像素點上的BGR值不同而展開。 對于彩色圖像,每個像素點上的BGR值為三個整數,因為是三通道圖像;對于灰度圖像,各個像素上的BGR值是一個整數,因為這是單通…

Kafka ACL(訪問控制列表)介紹

文章目錄 Kafka ACL(訪問控制列表)介紹1. Kafka ACL 的基本概念1.1 Kafka ACL 的目標1.2 Kafka ACL 的組成部分 2. Kafka 支持的資源類型2.1 Topic(主題)2.2 Consumer Group(消費者組)2.3 Cluster&#xff…

在 WSL2 中重啟 Ubuntu 實例

在 WSL2 中重啟 Ubuntu 實例,可以按照以下步驟操作: 方法 1: 使用 wsl 命令 關閉 Ubuntu 實例: 打開 PowerShell 或命令提示符,運行以下命令: wsl --shutdown這會關閉所有 WSL2 實例。 重新啟動 Ubuntu: 再次打開 Ubuntu&#x…

Spring Boot 2 快速教程:WebFlux處理流程(五)

WebFlux請求處理流程 下面是spring mvc的請求處理流程 具體步驟: 第一步:發起請求到前端控制器(DispatcherServlet) 第二步:前端控制器請求HandlerMapping查找 Handler (可以根據xml配置、注解進行查找) 匹配條件包括…

小程序設計和開發:如何研究同類型小程序的優點和不足。

一、確定研究目標和范圍 明確研究目的 在開始研究同類型小程序之前,首先需要明確研究的目的。是為了改進自己的小程序設計和開發,還是為了了解市場趨勢和用戶需求?不同的研究目的會影響研究的方法和重點。例如,如果研究目的是為了…

使用 Numpy 自定義數據集,使用pytorch框架實現邏輯回歸并保存模型,然后保存模型后再加載模型進行預測,對預測結果計算精確度和召回率及F1分數

1. 導入必要的庫 首先,導入我們需要的庫:Numpy、Pytorch 和相關工具包。 import numpy as np import torch import torch.nn as nn import torch.optim as optim from sklearn.metrics import accuracy_score, recall_score, f1_score2. 自定義數據集 …

Unity-編譯構建Android的問題記錄

文章目錄 報錯:AAPT2 aapt2-4.1.2-6503028-osx Daemon #0 Failed to shutdown within timeout報錯信息解讀:原因分析最終處理方法 報錯:AAPT2 aapt2-4.1.2-6503028-osx Daemon #0 Failed to shutdown within timeout 報錯信息解讀&#xff1…

【axios二次封裝】

axios二次封裝 安裝封裝使用 安裝 pnpm add axios封裝 // 進行axios二次封裝:使用請求與響應攔截器 import axios from axios import { ElMessage } from element-plus//創建axios實例 const request axios.create({baseURL: import.meta.env.VITE_APP_BASE_API,…

SQL進階實戰技巧:如何構建用戶行為轉移概率矩陣,深入洞察會話內活動流轉?

目錄 1 場景描述 1.1 用戶行為轉移概率矩陣概念 1.2 用戶行為轉移概率矩陣構建方法 (1) 數據收集

Vue3.0實戰:大數據平臺可視化(附完整項目源碼)

文章目錄 創建vue3.0項目項目初始化項目分辨率響應式設置項目頂部信息條創建頁面主體創建全局引入echarts和axios后臺接口創建express銷售總量圖實現完整項目下載項目任何問題都可在評論區,或者直接私信即可。 創建vue3.0項目 創建項目: vue create vueecharts選擇第三項:…

Java自定義IO密集型和CPU密集型線程池

文章目錄 前言線程池各類場景描述常見場景案例設計思路公共類自定義工廠類-MyThreadFactory自定義拒絕策略-RejectedExecutionHandlerFactory自定義阻塞隊列-TaskQueue(實現 核心線程->最大線程數->隊列) 場景1:CPU密集型場景思路&…