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

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

開發(fā) 前端
Linux 系統(tǒng)中,傳統(tǒng)的訪問方式是通過 write() 和 read() 兩個系統(tǒng)調(diào)用實現(xiàn)的,通過 read() ?函數(shù)讀取文件到到緩存區(qū)中,然后通過 write() 方法把緩存中的數(shù)據(jù)輸出到網(wǎng)絡(luò)端口 。

零拷貝技術(shù) Zero-Copy 是指計算機執(zhí)行操作時,可以直接從源(如文件或網(wǎng)絡(luò)套接字)將數(shù)據(jù)傳輸?shù)侥繕司彌_區(qū), 而不需要 CPU 先將數(shù)據(jù)從某處內(nèi)存復(fù)制到另一個特定區(qū)域,從而減少上下文切換以及 CPU 的拷貝時間。

1 I/O 中斷原理

在 DMA 技術(shù)出現(xiàn)之前,應(yīng)用程序與磁盤之間的 I/O 操作都是通過 CPU 的中斷完成的。

圖片圖片

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

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

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

2 DMA 方式

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

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

圖片圖片

基于 DMA 訪問方式,系統(tǒng)主內(nèi)存于硬盤或網(wǎng)卡之間的數(shù)據(jù)傳輸可以繞開 CPU 的全程調(diào)度,數(shù)據(jù)搬運的工作交給 DMA 控制器,在傳輸過程中,CPU 可以繼續(xù)處理其他的工作,提升系統(tǒng)的資源利用率。

圖片圖片

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

3 傳統(tǒng) I/O 方式

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

Linux 系統(tǒng)中,傳統(tǒng)的訪問方式是通過 write() 和 read() 兩個系統(tǒng)調(diào)用實現(xiàn)的,通過 read()  函數(shù)讀取文件到到緩存區(qū)中,然后通過 write() 方法把緩存中的數(shù)據(jù)輸出到網(wǎng)絡(luò)端口 。

圖片圖片

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

圖片圖片

  • 4 次上下文切換

因為發(fā)生了兩次系統(tǒng)調(diào)用,一次是 read() ,一次是 write(),用戶程序向內(nèi)核發(fā)起系統(tǒng)調(diào)用時,CPU 將用戶進程從用戶態(tài)切換到內(nèi)核態(tài);當(dāng)系統(tǒng)調(diào)用返回時,CPU 將用戶進程從內(nèi)核態(tài)切換回用戶態(tài)。

  • 4 次 數(shù)據(jù)拷貝
  • 第一次 DMA 拷貝,將磁盤上的數(shù)據(jù)拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū) ;
  • 第二次 CPU 拷貝,將內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到用戶的緩沖區(qū)里;
  • 第三次 CPU 拷貝,將用戶緩沖區(qū)的數(shù)據(jù),拷貝到內(nèi)核 Socket 緩沖區(qū);
  • 第四次 DMA 拷貝,將內(nèi)核 Socket 緩沖區(qū)的數(shù)據(jù)拷貝到網(wǎng)卡的緩沖區(qū)。

綜上,想要提升文件傳輸?shù)男阅埽虼宋覀冃枰獪p少「上下文切換」和「數(shù)據(jù)拷貝」的次數(shù)。

3 零拷貝方式

零拷貝技術(shù)實現(xiàn)的方式通常有 2 種:mmap + write 、sendfile、sendfile + DMA scatter-gather 。

3.1 mmap + write

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

圖片圖片

基于 mmap + write 系統(tǒng)調(diào)用的零拷貝方式,整個拷貝過程會發(fā)生 4 次上下文切換,1 次 CPU 拷貝和 2 次 DMA 拷貝。

圖片圖片

用戶程序讀寫數(shù)據(jù)的流程如下:

  • 用戶進程通過 mmap() 函數(shù)向內(nèi)核發(fā)起系統(tǒng)調(diào)用,上下文從用戶態(tài)切換為內(nèi)核態(tài)。
  • 將用戶進程的內(nèi)核空間的讀緩沖區(qū)與用戶空間的緩存區(qū)進行內(nèi)存地址映射。
  • CPU 利用 DMA 控制器將數(shù)據(jù)從主存或硬盤拷貝到內(nèi)核空間的讀緩沖區(qū)。
  • 上下文從內(nèi)核態(tài)切換回用戶態(tài),mmap 系統(tǒng)調(diào)用執(zhí)行返回。
  • 用戶進程通過 write() 函數(shù)向內(nèi)核發(fā)起系統(tǒng)調(diào)用,上下文從用戶態(tài)切換為內(nèi)核態(tài)。
  • CPU 將讀緩沖區(qū)中的數(shù)據(jù)拷貝到的網(wǎng)絡(luò)緩沖區(qū)。
  • CPU 利用 DMA 控制器將數(shù)據(jù)從網(wǎng)絡(luò)緩沖區(qū)(socket buffer)拷貝到網(wǎng)卡進行數(shù)據(jù)傳輸。
  • 上下文從內(nèi)核態(tài)切換回用戶態(tài),write 系統(tǒng)調(diào)用執(zhí)行返回。

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

當(dāng) mmap 一個文件時,如果這個文件被另一個進程所截獲,那么 write 系統(tǒng)調(diào)用會因為訪問非法地址被 SIGBUS 信號終止,SIGBUS 默認會殺死進程并產(chǎn)生一個 coredump,服務(wù)器可能因此被終止。

3.2 sendfile

sendfile 系統(tǒng)調(diào)用在 Linux 內(nèi)核版本 2.1 中被引入,目的是簡化通過網(wǎng)絡(luò)在兩個通道之間進行的數(shù)據(jù)傳輸過程。

通過 sendfile 系統(tǒng)調(diào)用,數(shù)據(jù)可以直接在內(nèi)核空間內(nèi)部進行 I/O 傳輸,從而省去了數(shù)據(jù)在用戶空間和內(nèi)核空間之間的來回拷貝。

sendfile 系統(tǒng)調(diào)用的引入,不僅減少了 CPU 拷貝的次數(shù),還減少了上下文切換的次數(shù),它的偽代碼如下:

圖片圖片

基于 sendfile 系統(tǒng)調(diào)用的零拷貝方式,整個拷貝過程會發(fā)生 2 次上下文切換,1 次 CPU 拷貝和 2 次 DMA 拷貝。

圖片圖片

用戶程序讀寫數(shù)據(jù)的流程如下:

  • 用戶進程通過 sendfile() 函數(shù)向內(nèi)核發(fā)起系統(tǒng)調(diào)用,上下文從用戶態(tài)切換為內(nèi)核態(tài)。
  • CPU 利用 DMA 控制器將數(shù)據(jù)從主存或硬盤拷貝到內(nèi)核空間的讀緩沖區(qū)。
  • CPU 將讀緩沖區(qū)中的數(shù)據(jù)拷貝到的網(wǎng)絡(luò)緩沖區(qū)。
  • CPU 利用 DMA 控制器將數(shù)據(jù)從網(wǎng)絡(luò)緩沖區(qū)拷貝到網(wǎng)卡進行數(shù)據(jù)傳輸。
  • 上下文從內(nèi)核態(tài)切換回用戶態(tài),sendfile 系統(tǒng)調(diào)用執(zhí)行返回。

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

3.3 sendfile + DMA gather copy

Linux 2.4 版本的內(nèi)核對 sendfile 系統(tǒng)調(diào)用進行修改,為 DMA 拷貝引入了 gather 操作。

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

圖片圖片

在硬件的支持下,sendfile 拷貝方式不再從內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到 socket 緩沖區(qū),取而代之的僅僅是緩沖區(qū)文件描述符和數(shù)據(jù)長度的拷貝,這樣 DMA 引擎直接利用 gather 操作將頁緩存中數(shù)據(jù)打包發(fā)送到網(wǎng)絡(luò)中即可,本質(zhì)就是和虛擬內(nèi)存映射的思路類似。

圖片圖片

基于 sendfile + DMA gather copy 系統(tǒng)調(diào)用的零拷貝方式,整個拷貝過程會發(fā)生 2 次上下文切換、0 次 CPU 拷貝以及 2 次 DMA 拷貝,用戶程序讀寫數(shù)據(jù)的流程如下:

  • 用戶進程通過 sendfile() 函數(shù)向內(nèi)核發(fā)起系統(tǒng)調(diào)用,上下文從用戶態(tài)切換為內(nèi)核態(tài)。
  • CPU 利用 DMA 控制器將數(shù)據(jù)從主存或硬盤拷貝到內(nèi)核空間的讀緩沖區(qū)。
  • CPU 把讀緩沖區(qū)的文件描述符(file descriptor)和數(shù)據(jù)長度拷貝到網(wǎng)絡(luò)緩沖區(qū)。
  • 基于已拷貝的文件描述符和數(shù)據(jù)長度,CPU 利用 DMA 控制器的 gather/scatter 操作直接批量地將數(shù)據(jù)從內(nèi)核的讀緩沖區(qū)拷貝到網(wǎng)卡進行數(shù)據(jù)傳輸。
  • 上下文從內(nèi)核態(tài)切換回用戶態(tài),sendfile 系統(tǒng)調(diào)用執(zhí)行返回。

5 寫到最后

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

拷貝方式

CPU拷貝

DMA拷貝

系統(tǒng)調(diào)用

上下文切換

傳統(tǒng)方式(read + write)

2

2

read / write

4

內(nèi)存映射(mmap + write)

1

2

mmap / write

4

sendfile

1

2

sendfile

2

sendfile + DMA gather copy

0

2

sendfile

2

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

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

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

責(zé)任編輯:武曉燕 來源: 勇哥Java實戰(zhàn)
相關(guān)推薦

2022-10-09 07:33:38

JavaSPI程序

2022-09-23 08:47:01

DMA網(wǎng)卡CPU

2017-09-07 14:44:10

程序員

2024-12-26 17:04:47

2011-04-27 09:30:48

企業(yè)架構(gòu)

2020-10-14 06:22:14

UWB技術(shù)感知

2020-09-27 06:53:57

MavenCDNwrapper

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文件

2021-09-03 09:12:09

Linux中斷軟件

2019-10-30 10:13:15

區(qū)塊鏈技術(shù)支付寶

2010-04-22 14:14:29

Live-USB

2020-08-04 14:20:20

數(shù)據(jù)湖Hadoop數(shù)據(jù)倉庫

2021-09-01 23:29:37

Golang語言gRPC

2021-01-21 21:24:34

DevOps開發(fā)工具

2021-02-05 10:03:31

區(qū)塊鏈技術(shù)智能

2020-03-05 10:28:19

MySQLMRR磁盤讀

2023-07-12 15:32:49

人工智能AI
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 最新日韩欧美 | 久久网亚洲 | 久久精品国产一区二区电影 | 7777在线| 欧美视频在线播放 | 91精品国产一二三 | 欧美综合一区 | 欧美一区不卡 | 日韩精品在线观看免费 | 在线观看国产精品一区二区 | 日韩综合在线播放 | 少妇av片| 亚洲视频一区在线观看 | 免费亚洲网站 | 日韩欧美高清dvd碟片 | 日本91av视频| 亚洲精品在线免费观看视频 | 雨宫琴音一区二区在线 | 成人三区四区 | 日韩一区二区在线看 | 国产av毛片 | 无码国模国产在线观看 | 国产乱码精品一区二三赶尸艳谈 | 污片在线免费观看 | 韩日av在线 | 看片一区| 自拍偷拍中文字幕 | 午夜精品一区二区三区在线观看 | 在线观看免费毛片 | 九九精品视频在线 | 国产福利在线视频 | 欧美精品成人一区二区三区四区 | 成人精品久久日伦片大全免费 | 亚洲一区二区三区国产 | 91免费看片 | 国产一区二区精品在线观看 | 秋霞国产| 婷婷久久综合 | av一二三区| 亚洲综合精品 | 国产99久久精品 |