了解Linux 和 Java 的零拷貝
Linux傳統IO
Linux傳統IO
Linux傳統上的資料。現在要把我從磁碟發到網卡,需要經過以下步驟:
#如上圖:作業系統把記憶體分為了核心空間和使用者空間。首先位於使用者空間的應用程式使用發起資料讀取操作,例如JVM發起read()系統呼叫。這時候作業系統會進行一次
上下文切換:從使用者空間切換到核心空間。最後進行上下文切換,再換回使用者空間的上下文。然後核心空間通知磁碟,核心把我從磁碟copy到核心緩衝區。這個過程是由一個叫做「DMA(Direct memory access)」的硬體來做的,所以不需要CPU的參與。
然後核心把我從核心緩衝區copy到應用程式緩衝區,這裡需要CPU的參與。
整個讀取操作的過程需要兩次上下文切換和兩次copy
。相關學習推薦:Java影片教學
寫操作
#寫操作與讀取操作類似,只是方向相反而已,仍然需要兩次上下文切換和兩次資料的copy。我可能會被寫到磁碟,也可能會被寫到網卡。
記憶體映射
現在主流的作業系統都使用了虛擬記憶體
。簡單來說,就是用虛擬位址取代實體位址
,這樣做可以讓多個虛擬記憶體只想同一個實體位址,虛擬記憶體的空間可以遠大於實體記憶體的空間。- 那如果作業系統能夠把使用者空間的應用程式緩衝區和核心空間的核心緩衝區映射到同一個實體位址,那豈不是就少了很多複製的過程?如下圖:
Linux零拷貝
所以為了解決這個問題,聰明的Linux開發者們寫了一些新的系統呼叫來做這個事。主要有兩種方式:mmap write
mmap write
mmap()
使用戶緩衝區和核心讀取緩衝區的記憶體位址為同一記憶體位址,也就是說,不需要CPU再將我從核心讀取緩衝區複製到用戶緩衝區啦!
當使用write()
系統呼叫的時候,CPU將我從核心緩衝區(等同於使用者緩衝區)直接寫入到需要傳送的核心緩衝區,例如網路發送緩衝區(socket buffer)
,然後透過DMA的方式將我傳入到網卡驅動程式(或磁碟)中準備發送。 ###############mmap write的方式讀寫資料總共需要兩次系統調用,4次上下文切換,2次DMA Copy和1次CPU Copy。 ############sendfile######sendfile也是一個系統調用,它其實本質上就是把上述兩個系統調用的函數合起來,變成了一個調用。這樣做的好處是,作業系統只需要2次上下文切換了,減少了2次上下文切換的開銷。 ###了解Linux 和 Java 的零拷貝
Linux2.4核心對sendfile進行了優化,提供了了解Linux 和 Java 的零拷貝操作,這個操作可以把上圖中的最後一次CPU copy去掉,原理就是不複製數據,而是把資料在之前的核心緩衝區(比如圖中的案例是Read Buffer)的記憶體位址、偏移記錄傳送給目標核心緩衝區(比如圖中案例的Socket Buffer),這樣在最後的DMA copy階段就可以拿著這個指標直接去找資料copy了。
Java NIO使用零拷貝
Linux的零拷貝確實能夠節省一些作業系統的資源。所以Java的NIO為了支援零拷貝,提供了一些類別:
- DirectByteBuffer
- FileChannel
在之前的《Java NIO - Buffer》這篇文章裡大概介紹了DirectByteBuffer。 ByteBuffer主要有兩種實現,一種是DirectByteBuffer, 一種是HeapByteBuffer。
其中,DirectByteBuffer直接在堆外分配內存,底層是直接透過JNI調用作業系統的NIO系統調用,所以效能會比較高。而HeapByteBuffer是堆內內存,而且資料需要多一次拷貝,所以效能比較低。
FileChannel
是Java NIO提供的複製檔案的類,可以把檔案複製到磁碟或網路等。
map
方法其實就是採用了作業系統中的記憶體映射方式,將核心緩衝區的記憶體和使用者緩衝區的記憶體做了一個位址映射。
transferTo
方法直接將目前頻道內容傳送到另一個頻道,也就是說這種方式不會有核心緩衝區到使用者緩衝區的讀寫問題。底層是sendfile系統呼叫。 transferFrom
方法同理。
範例程式碼:
File file = new File("test.txt");RandomAccessFile raf = new RandomAccessFile(file, "rw");FileChannel fileChannel = raf.getChannel();SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("", 8080));// 直接使用了transferTo()进行通道间的数据传输fileChannel.transferTo(0, fileChannel.size(), socketChannel);
作者:公眾號_xy的技術圈
#連結:www.imooc.com/article/289550
#來源:慕課網
以上內容來自幕課網
零拷貝的再次理解
零拷貝,是從操作系統的角度來說的。因為內核緩衝區之間,沒有資料是重複的(只有 kernel buffer 有一份資料)。
零拷貝不僅帶來更少的資料複製,還能帶來其他的效能優勢,例如更少的上下文切換,更少的CPU 快取偽共享以及無CPU校驗和計算。
mmap和sendFile的差異
#mmap 適合小資料量讀寫,sendFile 適合大檔案傳輸。
mmap 需要 4 次上下文切換,3 次資料拷貝;sendFile 需要 3 次上下文切換,最少 2 次資料拷貝。
sendFile 可以利用 DMA 方式,減少 CPU 拷貝,mmap 則不能(必須從核心拷貝到 Socket 緩衝區)。
以上是了解Linux 和 Java 的零拷貝的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

CentOS 和 Ubuntu 的關鍵差異在於:起源(CentOS 源自 Red Hat,面向企業;Ubuntu 源自 Debian,面向個人)、包管理(CentOS 使用 yum,注重穩定;Ubuntu 使用 apt,更新頻率高)、支持週期(CentOS 提供 10 年支持,Ubuntu 提供 5 年 LTS 支持)、社區支持(CentOS 側重穩定,Ubuntu 提供廣泛教程和文檔)、用途(CentOS 偏向服務器,Ubuntu 適用於服務器和桌面),其他差異包括安裝精簡度(CentOS 精

CentOS 安裝步驟:下載 ISO 映像並刻錄可引導媒體;啟動並選擇安裝源;選擇語言和鍵盤佈局;配置網絡;分區硬盤;設置系統時鐘;創建 root 用戶;選擇軟件包;開始安裝;安裝完成後重啟並從硬盤啟動。

CentOS 已停止維護,替代選擇包括:1. Rocky Linux(兼容性最佳);2. AlmaLinux(與 CentOS 兼容);3. Ubuntu Server(需要配置);4. Red Hat Enterprise Linux(商業版,付費許可);5. Oracle Linux(與 CentOS 和 RHEL 兼容)。在遷移時,考慮因素有:兼容性、可用性、支持、成本和社區支持。

如何使用 Docker Desktop? Docker Desktop 是一款工具,用於在本地機器上運行 Docker 容器。其使用步驟包括:1. 安裝 Docker Desktop;2. 啟動 Docker Desktop;3. 創建 Docker 鏡像(使用 Dockerfile);4. 構建 Docker 鏡像(使用 docker build);5. 運行 Docker 容器(使用 docker run)。

Docker利用Linux內核特性,提供高效、隔離的應用運行環境。其工作原理如下:1. 鏡像作為只讀模板,包含運行應用所需的一切;2. 聯合文件系統(UnionFS)層疊多個文件系統,只存儲差異部分,節省空間並加快速度;3. 守護進程管理鏡像和容器,客戶端用於交互;4. Namespaces和cgroups實現容器隔離和資源限制;5. 多種網絡模式支持容器互聯。理解這些核心概念,才能更好地利用Docker。

Docker 進程查看方法:1. Docker CLI 命令:docker ps;2. Systemd CLI 命令:systemctl status docker;3. Docker Compose CLI 命令:docker-compose ps;4. Process Explorer(Windows);5. /proc 目錄(Linux)。

Docker鏡像構建失敗的故障排除步驟:檢查Dockerfile語法和依賴項版本。檢查構建上下文中是否包含所需源代碼和依賴項。查看構建日誌以獲取錯誤詳細信息。使用--target選項構建分層階段以識別失敗點。確保使用最新版本的Docker引擎。使用--t [image-name]:debug模式構建鏡像以調試問題。檢查磁盤空間並確保足夠。禁用SELinux以防止干擾構建過程。向社區平台尋求幫助,提供Dockerfile和構建日誌描述以獲得更具體的建議。

VS Code 系統要求:操作系統:Windows 10 及以上、macOS 10.12 及以上、Linux 發行版處理器:最低 1.6 GHz,推薦 2.0 GHz 及以上內存:最低 512 MB,推薦 4 GB 及以上存儲空間:最低 250 MB,推薦 1 GB 及以上其他要求:穩定網絡連接,Xorg/Wayland(Linux)
