成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java Nio,Netty,Kafka 中經常提到“零拷貝”到底是什么?

開發 前端
Linux 系統中,傳統的訪問方式是通過 write() 和 read() 兩個系統調用實現的,通過 read() ?函數讀取文件到到緩存區中,然后通過 write() 方法把緩存中的數據輸出到網絡端口 。

零拷貝技術 Zero-Copy 是指計算機執行操作時,可以直接從源(如文件或網絡套接字)將數據傳輸到目標緩沖區, 而不需要 CPU 先將數據從某處內存復制到另一個特定區域,從而減少上下文切換以及 CPU 的拷貝時間。

1 I/O 中斷原理

在 DMA 技術出現之前,應用程序與磁盤之間的 I/O 操作都是通過 CPU 的中斷完成的。

圖片圖片

  • 用戶進程向 CPU 發起 read 系統調用讀取數據,由用戶態切換為內核態,然后一直阻塞等待數據的返回。
  • CPU 在接收到指令以后對磁盤發起 I/O 請求,將磁盤數據先放入磁盤控制器緩沖區。
  • 數據準備完成以后,磁盤向 CPU 發起 I/O 中斷。
  • CPU 收到 I/O 中斷以后將磁盤緩沖區中的數據拷貝到內核緩沖區,然后再從內核緩沖區拷貝到用戶緩沖區。
  • 用戶進程由內核態切換回用戶態,解除阻塞狀態,然后等待 CPU 的下一個執行時間鐘。

可以看到,整個數據的傳輸過程,都要需要 CPU 親自參與搬運數據的過程,而且這個過程,CPU 是不能做其他事情的。

假如通過千兆網卡或者磁盤傳輸大量數據時,使用 CPU 來拷貝的話,對 CPU 資源是種極大的消耗。

2 DMA 方式

DMA 的全稱是直接內存訪問(Direct Memory Access),是一種硬件設備繞開 CPU 獨立直接訪問內存的機制。

目前支持 DMA 的硬件包括:網卡、聲卡、顯卡、磁盤控制器等。

圖片圖片

基于 DMA 訪問方式,系統主內存于硬盤或網卡之間的數據傳輸可以繞開 CPU 的全程調度,數據搬運的工作交給 DMA 控制器,在傳輸過程中,CPU 可以繼續處理其他的工作,提升系統的資源利用率。

圖片圖片

  • 用戶進程向 CPU 發起 read 系統調用讀取數據,用戶態切換為內核態,然后一直阻塞等待數據的返回。
  • CPU 在接收到指令以后對 DMA 磁盤控制器發起調度指令。
  • DMA 磁盤控制器對磁盤發起 I/O 請求,將磁盤數據先拷貝到磁盤控制器緩沖區,CPU 全程不參與此過程。
  • 數據讀取完成后,DMA 磁盤控制器會接受到磁盤的通知,將數據從磁盤控制器緩沖區拷貝到內核緩沖區。
  • DMA 磁盤控制器向 CPU 發出數據讀完的信號,由 CPU 負責將數據從內核緩沖區拷貝到用戶緩沖區。
  • 用戶進程由內核態切換回用戶態,解除阻塞狀態,然后等待 CPU 的下一個執行時間鐘。

3 傳統 I/O 方式

為了理解零拷貝技術的思路,首先了解一下傳統 I/O 方式存在的問題。

Linux 系統中,傳統的訪問方式是通過 write() 和 read() 兩個系統調用實現的,通過 read()  函數讀取文件到到緩存區中,然后通過 write() 方法把緩存中的數據輸出到網絡端口 。

圖片圖片

下圖分別對應傳統 I/O 操作的數據讀寫流程,整個過程涉及 4 次上下文切換、 2 次 CPU 拷貝、2 次 DMA 拷貝總共 4 次拷貝

圖片圖片

  • 4 次上下文切換

因為發生了兩次系統調用,一次是 read() ,一次是 write(),用戶程序向內核發起系統調用時,CPU 將用戶進程從用戶態切換到內核態;當系統調用返回時,CPU 將用戶進程從內核態切換回用戶態。

  • 4 次 數據拷貝
  • 第一次 DMA 拷貝,將磁盤上的數據拷貝到操作系統內核的緩沖區 ;
  • 第二次 CPU 拷貝,將內核緩沖區的數據拷貝到用戶的緩沖區里;
  • 第三次 CPU 拷貝,將用戶緩沖區的數據,拷貝到內核 Socket 緩沖區;
  • 第四次 DMA 拷貝,將內核 Socket 緩沖區的數據拷貝到網卡的緩沖區。

綜上,想要提升文件傳輸的性能,因此我們需要減少「上下文切換」和「數據拷貝」的次數。

3 零拷貝方式

零拷貝技術實現的方式通常有 2 種:mmap + write 、sendfile、sendfile + DMA scatter-gather 。

3.1 mmap + write

mmap 是 Linux 提供的一種內存映射文件的機制,它實現了將內核中讀緩沖區地址與用戶空間緩沖區地址進行映射,從而實現內核緩沖區與用戶緩沖區的共享。

圖片圖片

基于 mmap + write 系統調用的零拷貝方式,整個拷貝過程會發生 4 次上下文切換,1 次 CPU 拷貝和 2 次 DMA 拷貝。

圖片圖片

用戶程序讀寫數據的流程如下:

  • 用戶進程通過 mmap() 函數向內核發起系統調用,上下文從用戶態切換為內核態。
  • 將用戶進程的內核空間的讀緩沖區與用戶空間的緩存區進行內存地址映射。
  • CPU 利用 DMA 控制器將數據從主存或硬盤拷貝到內核空間的讀緩沖區。
  • 上下文從內核態切換回用戶態,mmap 系統調用執行返回。
  • 用戶進程通過 write() 函數向內核發起系統調用,上下文從用戶態切換為內核態。
  • CPU 將讀緩沖區中的數據拷貝到的網絡緩沖區。
  • CPU 利用 DMA 控制器將數據從網絡緩沖區(socket buffer)拷貝到網卡進行數據傳輸。
  • 上下文從內核態切換回用戶態,write 系統調用執行返回。

mmap 的拷貝雖然減少了 1 次 CPU 拷貝,提升了效率,但也存在一些隱藏的問題。

當 mmap 一個文件時,如果這個文件被另一個進程所截獲,那么 write 系統調用會因為訪問非法地址被 SIGBUS 信號終止,SIGBUS 默認會殺死進程并產生一個 coredump,服務器可能因此被終止。

3.2 sendfile

sendfile 系統調用在 Linux 內核版本 2.1 中被引入,目的是簡化通過網絡在兩個通道之間進行的數據傳輸過程。

通過 sendfile 系統調用,數據可以直接在內核空間內部進行 I/O 傳輸,從而省去了數據在用戶空間和內核空間之間的來回拷貝。

sendfile 系統調用的引入,不僅減少了 CPU 拷貝的次數,還減少了上下文切換的次數,它的偽代碼如下:

圖片圖片

基于 sendfile 系統調用的零拷貝方式,整個拷貝過程會發生 2 次上下文切換,1 次 CPU 拷貝和 2 次 DMA 拷貝。

圖片圖片

用戶程序讀寫數據的流程如下:

  • 用戶進程通過 sendfile() 函數向內核發起系統調用,上下文從用戶態切換為內核態。
  • CPU 利用 DMA 控制器將數據從主存或硬盤拷貝到內核空間的讀緩沖區。
  • CPU 將讀緩沖區中的數據拷貝到的網絡緩沖區。
  • CPU 利用 DMA 控制器將數據從網絡緩沖區拷貝到網卡進行數據傳輸。
  • 上下文從內核態切換回用戶態,sendfile 系統調用執行返回。

相比較于 mmap 內存映射的方式,sendfile 少了 2 次上下文切換,但是仍然有 1 次 CPU 拷貝操作。

3.3 sendfile + DMA gather copy

Linux 2.4 版本的內核對 sendfile 系統調用進行修改,為 DMA 拷貝引入了 gather 操作。

它將內核空間的讀緩沖區中對應的數據描述信息(內存地址、地址偏移量)記錄到相應的網絡緩沖區中,由 DMA 根據內存地址、地址偏移量將數據批量地從讀緩沖區拷貝到網卡設備中,這樣就省去了內核空間中僅剩的 1 次 CPU 拷貝操作。

圖片圖片

在硬件的支持下,sendfile 拷貝方式不再從內核緩沖區的數據拷貝到 socket 緩沖區,取而代之的僅僅是緩沖區文件描述符和數據長度的拷貝,這樣 DMA 引擎直接利用 gather 操作將頁緩存中數據打包發送到網絡中即可,本質就是和虛擬內存映射的思路類似。

圖片圖片

基于 sendfile + DMA gather copy 系統調用的零拷貝方式,整個拷貝過程會發生 2 次上下文切換、0 次 CPU 拷貝以及 2 次 DMA 拷貝,用戶程序讀寫數據的流程如下:

  • 用戶進程通過 sendfile() 函數向內核發起系統調用,上下文從用戶態切換為內核態。
  • CPU 利用 DMA 控制器將數據從主存或硬盤拷貝到內核空間的讀緩沖區。
  • CPU 把讀緩沖區的文件描述符(file descriptor)和數據長度拷貝到網絡緩沖區。
  • 基于已拷貝的文件描述符和數據長度,CPU 利用 DMA 控制器的 gather/scatter 操作直接批量地將數據從內核的讀緩沖區拷貝到網卡進行數據傳輸。
  • 上下文從內核態切換回用戶態,sendfile 系統調用執行返回。

5 寫到最后

無論是傳統 I/O 拷貝方式還是引入零拷貝的方式,2 次 DMA 拷貝是都少不了的,因為兩次 DMA 都是依賴硬件完成的。

拷貝方式

CPU拷貝

DMA拷貝

系統調用

上下文切換

傳統方式(read + write)

2

2

read / write

4

內存映射(mmap + write)

1

2

mmap / write

4

sendfile

1

2

sendfile

2

sendfile + DMA gather copy

0

2

sendfile

2

RocketMQ 選擇了 mmap + write 這種零拷貝方式,適用于業務級消息這種小塊文件的數據持久化和傳輸;

而 Kafka 采用的是 sendfile 這種零拷貝方式,適用于系統日志消息這種高吞吐量的大塊文件的數據持久化和傳輸。

但是值得注意的一點是,Kafka 的索引文件使用的是 mmap + write 方式,數據文件使用的是 sendfile 方式。

責任編輯:武曉燕 來源: 勇哥Java實戰
相關推薦

2022-10-09 07:33:38

JavaSPI程序

2022-09-23 08:47:01

DMA網卡CPU

2017-09-07 14:44:10

程序員

2024-12-26 17:04:47

2011-04-27 09:30:48

企業架構

2020-09-27 06:53:57

MavenCDNwrapper

2020-10-14 06:22:14

UWB技術感知

2020-09-22 08:22:28

快充

2010-11-01 01:25:36

Windows NT

2023-10-11 08:29:54

volatileJava原子性

2013-06-09 09:47:31

.NetPDBPDB文件

2010-04-22 14:14:29

Live-USB

2019-10-30 10:13:15

區塊鏈技術支付寶

2021-09-03 09:12:09

Linux中斷軟件

2020-08-04 14:20:20

數據湖Hadoop數據倉庫

2021-01-21 21:24:34

DevOps開發工具

2021-07-07 05:07:15

JDKIterator迭代器

2023-07-12 15:32:49

人工智能AI

2024-02-04 00:01:00

云原生技術容器

2021-09-01 23:29:37

Golang語言gRPC
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美日韩久久久久 | 三级黄色网址 | 一区二区三区国产精品 | 亚洲一级毛片 | 成人免费一区二区三区牛牛 | 国产成人午夜高潮毛片 | 欧美亚洲在线 | 91中文字幕在线 | 久久久久亚洲 | 国产精品视频一 | 精品成人av | www.久久99| 久久久www| 亚洲成人免费视频 | jizz视频| 欧美日韩一区二区视频在线观看 | 久久综合久久久 | 97久久精品午夜一区二区 | 日韩中文不卡 | 丁香六月激情 | aaaa日韩| 在线欧美一区 | 一级欧美一级日韩片免费观看 | 台湾佬成人网 | 99精品国产一区二区青青牛奶 | 日日夜夜狠狠操 | 日本黄色高清视频 | 特级毛片 | 日韩国产一区 | 成人久草 | 91.xxx.高清在线 | av片在线免费看 | 国产视频三区 | 中文字幕日韩欧美一区二区三区 | 激情国产在线 | 国产91一区 | 在线免费观看色 | 黄色大片网 | 国产98色在线 | 日韩中文字幕免费在线 | 涩爱av一区二区三区 |