自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文搞懂什么是阻塞IO、信號驅(qū)動(dòng)IO、Reactor模型、零拷貝

存儲 存儲架構(gòu)
零拷貝技術(shù)的文件傳輸方式相比傳統(tǒng)文件傳輸?shù)姆绞?,減少了 2 次上下文切換和數(shù)據(jù)拷貝次數(shù),只需要 2 次上下文切換和數(shù)據(jù)拷貝次數(shù),就可以完成文件的傳輸,而且 2 次的數(shù)據(jù)拷貝過程,都不需要通過 CPU,2 次都是由 DMA 來搬運(yùn)。

基礎(chǔ)IO

如何從數(shù)據(jù)傳輸方式理解IO流?

從數(shù)據(jù)傳輸方式或者說是運(yùn)輸方式角度看,可以將 IO 類分為:

  1. 字節(jié)流, 字節(jié)流讀取單個(gè)字節(jié),字符流讀取單個(gè)字符(一個(gè)字符根據(jù)編碼的不同,對應(yīng)的字節(jié)也不同,如 UTF-8 編碼中文漢字是 3 個(gè)字節(jié),GBK編碼中文漢字是 2 個(gè)字節(jié)。)
  2. 字符流, 字節(jié)流用來處理二進(jìn)制文件(圖片、MP3、視頻文件),字符流用來處理文本文件(可以看做是特殊的二進(jìn)制文件,使用了某種編碼,人可以閱讀)。

字節(jié)是給計(jì)算機(jī)看的,字符才是給人看的

  • 字節(jié)流

圖片圖片

image.png

  • 字符流

圖片圖片

  • 字節(jié)轉(zhuǎn)字符?

圖片圖片

如何從數(shù)據(jù)操作上理解IO流?

從數(shù)據(jù)來源或者說是操作對象角度看,IO 類可以分為:

圖片圖片

Java IO設(shè)計(jì)上使用了什么設(shè)計(jì)模式?

裝飾者模式:所謂裝飾,就是把這個(gè)裝飾者套在被裝飾者之上,從而動(dòng)態(tài)擴(kuò)展被裝飾者的功能。

  • 裝飾者舉例

設(shè)計(jì)不同種類的飲料,飲料可以添加配料,比如可以添加牛奶,并且支持動(dòng)態(tài)添加新配料。每增加一種配料,該飲料的價(jià)格就會增加,要求計(jì)算一種飲料的價(jià)格。

下圖表示在 DarkRoast 飲料上新增新添加 Mocha 配料,之后又添加了 Whip 配料。DarkRoast 被 Mocha 包裹,Mocha 又被 Whip 包裹。它們都繼承自相同父類,都有 cost() 方法,外層類的 cost() 方法調(diào)用了內(nèi)層類的 cost() 方法。

圖片圖片

image.png

  • 以 InputStream 為例
  • InputStream 是抽象組件;
  • FileInputStream 是 InputStream 的子類,屬于具體組件,提供了字節(jié)流的輸入操作;
  • FilterInputStream 屬于抽象裝飾者,裝飾者用于裝飾組件,為組件提供額外的功能。例如 BufferedInputStream 為 FileInputStream 提供緩存的功能。

圖片圖片

image.png

實(shí)例化一個(gè)具有緩存功能的字節(jié)流對象時(shí),只需要在 FileInputStream 對象上再套一層 BufferedInputStream 對象即可。

FileInputStream fileInputStream = new FileInputStream(filePath);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

DataInputStream 裝飾者提供了對更多數(shù)據(jù)類型進(jìn)行輸入的操作,比如 int、double 等基本類型。

5種IO模型

什么是阻塞?什么是同步?

  • 阻塞IO 和 非阻塞IO

這兩個(gè)概念是程序級別的。主要描述的是程序請求操作系統(tǒng)IO操作后,如果IO資源沒有準(zhǔn)備好,那么程序該如何處理的問題: 前者等待;后者繼續(xù)執(zhí)行(并且使用線程一直輪詢,直到有IO資源準(zhǔn)備好了)

  • 同步IO 和 非同步IO

這兩個(gè)概念是操作系統(tǒng)級別的。主要描述的是操作系統(tǒng)在收到程序請求IO操作后,如果IO資源沒有準(zhǔn)備好,該如何響應(yīng)程序的問題: 前者不響應(yīng),直到IO資源準(zhǔn)備好以后;后者返回一個(gè)標(biāo)記(好讓程序和自己知道以后的數(shù)據(jù)往哪里通知),當(dāng)IO資源準(zhǔn)備好以后,再用事件機(jī)制返回給程序。

什么是Linux的IO模型?

網(wǎng)絡(luò)IO的本質(zhì)是socket的讀取,socket在linux系統(tǒng)被抽象為流,IO可以理解為對流的操作。剛才說了,對于一次IO訪問(以read舉例),數(shù)據(jù)會先被拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中,然后才會從操作系統(tǒng)內(nèi)核的緩沖區(qū)拷貝到應(yīng)用程序的地址空間。所以說,當(dāng)一個(gè)read操作發(fā)生時(shí),它會經(jīng)歷兩個(gè)階段:

  • 第一階段:等待數(shù)據(jù)準(zhǔn)備 (Waiting for the data to be ready)。
  • 第二階段:將數(shù)據(jù)從內(nèi)核拷貝到進(jìn)程中 (Copying the data from the kernel to the process)。

對于socket流而言,

  • 第一步:通常涉及等待網(wǎng)絡(luò)上的數(shù)據(jù)分組到達(dá),然后被復(fù)制到內(nèi)核的某個(gè)緩沖區(qū)。
  • 第二步:把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)。

網(wǎng)絡(luò)應(yīng)用需要處理的無非就是兩大類問題,網(wǎng)絡(luò)IO,數(shù)據(jù)計(jì)算。相對于后者,網(wǎng)絡(luò)IO的延遲,給應(yīng)用帶來的性能瓶頸大于后者。網(wǎng)絡(luò)IO的模型大致有如下幾種:

  1. 同步阻塞IO(bloking IO)
  2. 同步非阻塞IO(non-blocking IO)
  3. 多路復(fù)用IO(multiplexing IO)
  4. 信號驅(qū)動(dòng)式IO(signal-driven IO)
  5. 異步IO(asynchronous IO)

圖片圖片

什么是同步阻塞IO?

應(yīng)用進(jìn)程被阻塞,直到數(shù)據(jù)復(fù)制到應(yīng)用進(jìn)程緩沖區(qū)中才返回。

  • 舉例理解

你早上去買有現(xiàn)炸油條,你點(diǎn)單,之后一直等店家做好,期間你啥其它事也做不了。(你就是應(yīng)用級別,店家就是操作系統(tǒng)級別, 應(yīng)用被阻塞了不能做其它事)

  • Linux 中IO圖例

圖片圖片

image.png

什么是同步非阻塞IO?

應(yīng)用進(jìn)程執(zhí)行系統(tǒng)調(diào)用之后,內(nèi)核返回一個(gè)錯(cuò)誤碼。應(yīng)用進(jìn)程可以繼續(xù)執(zhí)行,但是需要不斷的執(zhí)行系統(tǒng)調(diào)用來獲知 I/O 是否完成,這種方式稱為輪詢(polling)。

  • 舉例理解

你早上去買現(xiàn)炸油條,你點(diǎn)單,點(diǎn)完后每隔一段時(shí)間詢問店家有沒有做好,期間你可以做點(diǎn)其它事情。(你就是應(yīng)用級別,店家就是操作系統(tǒng)級別,應(yīng)用可以做其它事情并通過輪詢來看操作系統(tǒng)是否完成)

  • Linux 中IO圖例

圖片圖片

image.png

什么是多路復(fù)用IO?

系統(tǒng)調(diào)用可能是由多個(gè)任務(wù)組成的,所以可以拆成多個(gè)任務(wù),這就是多路復(fù)用。

  • 舉例理解

你早上去買現(xiàn)炸油條,點(diǎn)單收錢和炸油條原來都是由一個(gè)人完成的,現(xiàn)在他成了瓶頸,所以專門找了個(gè)收銀員下單收錢,他則專注在炸油條。(本質(zhì)上炸油條是耗時(shí)的瓶頸,將他職責(zé)分離出不是瓶頸的部分,比如下單收銀,對應(yīng)到系統(tǒng)級別也時(shí)一樣的意思)

  • Linux 中IO圖例

使用 select 或者 poll 等待數(shù)據(jù),并且可以等待多個(gè)套接字中的任何一個(gè)變?yōu)榭勺x,這一過程會被阻塞,當(dāng)某一個(gè)套接字可讀時(shí)返回。之后再使用 recvfrom 把數(shù)據(jù)從內(nèi)核復(fù)制到進(jìn)程中。

它可以讓單個(gè)進(jìn)程具有處理多個(gè) I/O 事件的能力。又被稱為 Event Driven I/O,即事件驅(qū)動(dòng) I/O。

圖片圖片

有哪些多路復(fù)用IO?

目前流程的多路復(fù)用IO實(shí)現(xiàn)主要包括四種: select、poll、epoll、kqueue。下表是他們的一些重要特性的比較:

IO模型

相對性能

關(guān)鍵思路

操作系統(tǒng)

JAVA支持情況

select

較高

Reactor

windows/Linux

支持,Reactor模式(反應(yīng)器設(shè)計(jì)模式)。Linux操作系統(tǒng)的 kernels 2.4內(nèi)核版本之前,默認(rèn)使用select;而目前windows下對同步IO的支持,都是select模型

poll

較高

Reactor

Linux

Linux下的JAVA NIO框架,Linux kernels 2.6內(nèi)核版本之前使用poll進(jìn)行支持。也是使用的Reactor模式

epoll


Reactor/Proactor

Linux

Linux kernels 2.6內(nèi)核版本及以后使用epoll進(jìn)行支持;Linux kernels 2.6內(nèi)核版本之前使用poll進(jìn)行支持;另外一定注意,由于Linux下沒有Windows下的IOCP技術(shù)提供真正的 異步IO 支持,所以Linux下使用epoll模擬異步IO

kqueue


Proactor

Linux

目前JAVA的版本不支持

多路復(fù)用IO技術(shù)最適用的是“高并發(fā)”場景,所謂高并發(fā)是指1毫秒內(nèi)至少同時(shí)有上千個(gè)連接請求準(zhǔn)備好。其他情況下多路復(fù)用IO技術(shù)發(fā)揮不出來它的優(yōu)勢。另一方面,使用JAVA NIO進(jìn)行功能實(shí)現(xiàn),相對于傳統(tǒng)的Socket套接字實(shí)現(xiàn)要復(fù)雜一些,所以實(shí)際應(yīng)用中,需要根據(jù)自己的業(yè)務(wù)需求進(jìn)行技術(shù)選擇。

什么是信號驅(qū)動(dòng)IO?

應(yīng)用進(jìn)程使用 sigaction 系統(tǒng)調(diào)用,內(nèi)核立即返回,應(yīng)用進(jìn)程可以繼續(xù)執(zhí)行,也就是說等待數(shù)據(jù)階段應(yīng)用進(jìn)程是非阻塞的。內(nèi)核在數(shù)據(jù)到達(dá)時(shí)向應(yīng)用進(jìn)程發(fā)送 SIGIO 信號,應(yīng)用進(jìn)程收到之后在信號處理程序中調(diào)用 recvfrom 將數(shù)據(jù)從內(nèi)核復(fù)制到應(yīng)用進(jìn)程中。

相比于非阻塞式 I/O 的輪詢方式,信號驅(qū)動(dòng) I/O 的 CPU 利用率更高。

  • 舉例理解

你早上去買現(xiàn)炸油條,門口排隊(duì)的人多,現(xiàn)在引入了一個(gè)叫號系統(tǒng),點(diǎn)完單后你就可以做自己的事情了,然后等叫號就去拿就可以了。(所以不用再去自己頻繁跑去問有沒有做好了)

  • Linux 中IO圖例

圖片圖片

image.png

什么是異步IO?

相對于同步IO,異步IO不是順序執(zhí)行。用戶進(jìn)程進(jìn)行aio_read系統(tǒng)調(diào)用之后,無論內(nèi)核數(shù)據(jù)是否準(zhǔn)備好,都會直接返回給用戶進(jìn)程,然后用戶態(tài)進(jìn)程可以去做別的事情。等到socket數(shù)據(jù)準(zhǔn)備好了,內(nèi)核直接復(fù)制數(shù)據(jù)給進(jìn)程,然后從內(nèi)核向進(jìn)程發(fā)送通知。IO兩個(gè)階段,進(jìn)程都是非阻塞的。

  • 舉例理解

你早上去買現(xiàn)炸油條, 不用去排隊(duì)了,打開美團(tuán)外賣下單,然后做其它事,一會外賣自己送上門。(你就是應(yīng)用級別,店家就是操作系統(tǒng)級別, 應(yīng)用無需阻塞,這就是非阻塞;系統(tǒng)還可能在處理中,但是立刻響應(yīng)了應(yīng)用,這就是異步)

  • Linux 中IO圖例

(Linux提供了AIO庫函數(shù)實(shí)現(xiàn)異步,但是用的很少。目前有很多開源的異步IO庫,例如libevent、libev、libuv)

圖片圖片

什么是Reactor模型?

大多數(shù)網(wǎng)絡(luò)框架都是基于Reactor模型進(jìn)行設(shè)計(jì)和開發(fā),Reactor模型基于事件驅(qū)動(dòng),特別適合處理海量的I/O事件。

  • 傳統(tǒng)的IO模型?

這種模式是傳統(tǒng)設(shè)計(jì),每一個(gè)請求到來時(shí),大致都會按照:請求讀取->請求解碼->服務(wù)執(zhí)行->編碼響應(yīng)->發(fā)送答復(fù) 這個(gè)流程去處理。

圖片圖片

服務(wù)器會分配一個(gè)線程去處理,如果請求暴漲起來,那么意味著需要更多的線程來處理該請求。若請求出現(xiàn)暴漲,線程池的工作線程數(shù)量滿載那么其它請求就會出現(xiàn)等待或者被拋棄。若每個(gè)小任務(wù)都可以使用非阻塞的模式,然后基于異步回調(diào)模式。這樣就大大提高系統(tǒng)的吞吐量,這便引入了Reactor模型。

  • Reactor模型中定義的三種角色:
  1. Reactor:負(fù)責(zé)監(jiān)聽和分配事件,將I/O事件分派給對應(yīng)的Handler。新的事件包含連接建立就緒、讀就緒、寫就緒等。
  2. Acceptor:處理客戶端新連接,并分派請求到處理器鏈中。
  3. Handler:將自身與事件綁定,執(zhí)行非阻塞讀/寫任務(wù),完成channel的讀入,完成處理業(yè)務(wù)邏輯后,負(fù)責(zé)將結(jié)果寫出channel??捎觅Y源池來管理。
  • 單Reactor單線程模型

Reactor線程負(fù)責(zé)多路分離套接字,accept新連接,并分派請求到handler。Redis使用單Reactor單進(jìn)程的模型。

圖片圖片

image.png

消息處理流程:

  1. Reactor對象通過select監(jiān)控連接事件,收到事件后通過dispatch進(jìn)行轉(zhuǎn)發(fā)。
  2. 如果是連接建立的事件,則由acceptor接受連接,并創(chuàng)建handler處理后續(xù)事件。
  3. 如果不是建立連接事件,則Reactor會分發(fā)調(diào)用Handler來響應(yīng)。
  4. handler會完成read->業(yè)務(wù)處理->send的完整業(yè)務(wù)流程。
  • 單Reactor多線程模型

將handler的處理池化。

圖片圖片

  • 多Reactor多線程模型

主從Reactor模型:主Reactor用于響應(yīng)連接請求,從Reactor用于處理IO操作請求,讀寫分離了。

圖片圖片

什么是Java NIO?

NIO主要有三大核心部分:Channel(通道),Buffer(緩沖區(qū)), Selector。傳統(tǒng)IO基于字節(jié)流和字符流進(jìn)行操作,而NIO基于Channel和Buffer(緩沖區(qū))進(jìn)行操作,數(shù)據(jù)總是從通道讀取到緩沖區(qū)中,或者從緩沖區(qū)寫入到通道中。Selector(選擇區(qū))用于監(jiān)聽多個(gè)通道的事件(比如:連接打開,數(shù)據(jù)到達(dá))。因此,單個(gè)線程可以監(jiān)聽多個(gè)數(shù)據(jù)通道。

NIO和傳統(tǒng)IO(一下簡稱IO)之間第一個(gè)最大的區(qū)別是,IO是面向流的,NIO是面向緩沖區(qū)的。

圖片圖片

image.png

零拷貝

傳統(tǒng)的IO存在什么問題?為什么引入零拷貝的?

如果服務(wù)端要提供文件傳輸?shù)墓δ埽覀兡芟氲降淖詈唵蔚姆绞绞牵簩⒋疟P上的文件讀取出來,然后通過網(wǎng)絡(luò)協(xié)議發(fā)送給客戶端。

傳統(tǒng) I/O 的工作方式是,數(shù)據(jù)讀取和寫入是從用戶空間到內(nèi)核空間來回復(fù)制,而內(nèi)核空間的數(shù)據(jù)是通過操作系統(tǒng)層面的 I/O 接口從磁盤讀取或?qū)懭搿?/p>

代碼通常如下,一般會需要兩個(gè)系統(tǒng)調(diào)用:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

代碼很簡單,雖然就兩行代碼,但是這里面發(fā)生了不少的事情。

圖片圖片

首先,期間共發(fā)生了 4 次用戶態(tài)與內(nèi)核態(tài)的上下文切換,因?yàn)榘l(fā)生了兩次系統(tǒng)調(diào)用,一次是 read() ,一次是 write(),每次系統(tǒng)調(diào)用都得先從用戶態(tài)切換到內(nèi)核態(tài),等內(nèi)核完成任務(wù)后,再從內(nèi)核態(tài)切換回用戶態(tài)。

上下文切換到成本并不小,一次切換需要耗時(shí)幾十納秒到幾微秒,雖然時(shí)間看上去很短,但是在高并發(fā)的場景下,這類時(shí)間容易被累積和放大,從而影響系統(tǒng)的性能。

其次,還發(fā)生了 4 次數(shù)據(jù)拷貝,其中兩次是 DMA 的拷貝,另外兩次則是通過 CPU 拷貝的,下面說一下這個(gè)過程:

  • 第一次拷貝,把磁盤上的數(shù)據(jù)拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)里,這個(gè)拷貝的過程是通過 DMA 搬運(yùn)的。
  • 第二次拷貝,把內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到用戶的緩沖區(qū)里,于是我們應(yīng)用程序就可以使用這部分?jǐn)?shù)據(jù)了,這個(gè)拷貝到過程是由 CPU 完成的。
  • 第三次拷貝,把剛才拷貝到用戶的緩沖區(qū)里的數(shù)據(jù),再拷貝到內(nèi)核的 socket 的緩沖區(qū)里,這個(gè)過程依然還是由 CPU 搬運(yùn)的。
  • 第四次拷貝,把內(nèi)核的 socket 緩沖區(qū)里的數(shù)據(jù),拷貝到網(wǎng)卡的緩沖區(qū)里,這個(gè)過程又是由 DMA 搬運(yùn)的。

我們回過頭看這個(gè)文件傳輸?shù)倪^程,我們只是搬運(yùn)一份數(shù)據(jù),結(jié)果卻搬運(yùn)了 4 次,過多的數(shù)據(jù)拷貝無疑會消耗 CPU 資源,大大降低了系統(tǒng)性能。

這種簡單又傳統(tǒng)的文件傳輸方式,存在冗余的上文切換和數(shù)據(jù)拷貝,在高并發(fā)系統(tǒng)里是非常糟糕的,多了很多不必要的開銷,會嚴(yán)重影響系統(tǒng)性能。

所以,要想提高文件傳輸?shù)男阅埽托枰獪p少「用戶態(tài)與內(nèi)核態(tài)的上下文切換」和「內(nèi)存拷貝」的次數(shù)。

mmap + write怎么實(shí)現(xiàn)的零拷貝?

在前面我們知道,read() 系統(tǒng)調(diào)用的過程中會把內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到用戶的緩沖區(qū)里,于是為了減少這一步開銷,我們可以用 mmap() 替換 read() 系統(tǒng)調(diào)用函數(shù)。

buf = mmap(file, len);
write(sockfd, buf, len);

mmap() 系統(tǒng)調(diào)用函數(shù)會直接把內(nèi)核緩沖區(qū)里的數(shù)據(jù)「映射」到用戶空間,這樣,操作系統(tǒng)內(nèi)核與用戶空間就不需要再進(jìn)行任何的數(shù)據(jù)拷貝操作。

圖片圖片

image.png

具體過程如下:

  • 應(yīng)用進(jìn)程調(diào)用了 mmap() 后,DMA 會把磁盤的數(shù)據(jù)拷貝到內(nèi)核的緩沖區(qū)里。接著,應(yīng)用進(jìn)程跟操作系統(tǒng)內(nèi)核「共享」這個(gè)緩沖區(qū);
  • 應(yīng)用進(jìn)程再調(diào)用 write(),操作系統(tǒng)直接將內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到 socket 緩沖區(qū)中,這一切都發(fā)生在內(nèi)核態(tài),由 CPU 來搬運(yùn)數(shù)據(jù);
  • 最后,把內(nèi)核的 socket 緩沖區(qū)里的數(shù)據(jù),拷貝到網(wǎng)卡的緩沖區(qū)里,這個(gè)過程是由 DMA 搬運(yùn)的。

我們可以得知,通過使用 mmap() 來代替 read(), 可以減少一次數(shù)據(jù)拷貝的過程。

但這還不是最理想的零拷貝,因?yàn)槿匀恍枰ㄟ^ CPU 把內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到 socket 緩沖區(qū)里,而且仍然需要 4 次上下文切換,因?yàn)橄到y(tǒng)調(diào)用還是 2 次。

sendfile怎么實(shí)現(xiàn)的零拷貝?

在 Linux 內(nèi)核版本 2.1 中,提供了一個(gè)專門發(fā)送文件的系統(tǒng)調(diào)用函數(shù) sendfile(),函數(shù)形式如下:

#include <sys/socket.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

它的前兩個(gè)參數(shù)分別是目的端和源端的文件描述符,后面兩個(gè)參數(shù)是源端的偏移量和復(fù)制數(shù)據(jù)的長度,返回值是實(shí)際復(fù)制數(shù)據(jù)的長度。

首先,它可以替代前面的 read() 和 write() 這兩個(gè)系統(tǒng)調(diào)用,這樣就可以減少一次系統(tǒng)調(diào)用,也就減少了 2 次上下文切換的開銷。

其次,該系統(tǒng)調(diào)用,可以直接把內(nèi)核緩沖區(qū)里的數(shù)據(jù)拷貝到 socket 緩沖區(qū)里,不再拷貝到用戶態(tài),這樣就只有 2 次上下文切換,和 3 次數(shù)據(jù)拷貝。如下圖:

圖片圖片

但是這還不是真正的零拷貝技術(shù),如果網(wǎng)卡支持 SG-DMA(The Scatter-Gather Direct Memory Access)技術(shù)(和普通的 DMA 有所不同),我們可以進(jìn)一步減少通過 CPU 把內(nèi)核緩沖區(qū)里的數(shù)據(jù)拷貝到 socket 緩沖區(qū)的過程。

你可以在你的 Linux 系統(tǒng)通過下面這個(gè)命令,查看網(wǎng)卡是否支持 scatter-gather 特性:

$ ethtool -k eth0 | grep scatter-gather
scatter-gather: on

于是,從 Linux 內(nèi)核 2.4 版本開始起,對于支持網(wǎng)卡支持 SG-DMA 技術(shù)的情況下, sendfile() 系統(tǒng)調(diào)用的過程發(fā)生了點(diǎn)變化,具體過程如下:

  • 第一步,通過 DMA 將磁盤上的數(shù)據(jù)拷貝到內(nèi)核緩沖區(qū)里;
  • 第二步,緩沖區(qū)描述符和數(shù)據(jù)長度傳到 socket 緩沖區(qū),這樣網(wǎng)卡的 SG-DMA 控制器就可以直接將內(nèi)核緩存中的數(shù)據(jù)拷貝到網(wǎng)卡的緩沖區(qū)里,此過程不需要將數(shù)據(jù)從操作系統(tǒng)內(nèi)核緩沖區(qū)拷貝到 socket 緩沖區(qū)中,這樣就減少了一次數(shù)據(jù)拷貝;

所以,這個(gè)過程之中,只進(jìn)行了 2 次數(shù)據(jù)拷貝,如下圖:

圖片圖片

這就是所謂的零拷貝(Zero-copy)技術(shù),因?yàn)槲覀儧]有在內(nèi)存層面去拷貝數(shù)據(jù),也就是說全程沒有通過 CPU 來搬運(yùn)數(shù)據(jù),所有的數(shù)據(jù)都是通過 DMA 來進(jìn)行傳輸?shù)摹?/p>

零拷貝技術(shù)的文件傳輸方式相比傳統(tǒng)文件傳輸?shù)姆绞?,減少了 2 次上下文切換和數(shù)據(jù)拷貝次數(shù),只需要 2 次上下文切換和數(shù)據(jù)拷貝次數(shù),就可以完成文件的傳輸,而且 2 次的數(shù)據(jù)拷貝過程,都不需要通過 CPU,2 次都是由 DMA 來搬運(yùn)。

責(zé)任編輯:武曉燕 來源: 魯大猿
相關(guān)推薦

2024-08-08 14:57:32

2025-03-18 10:00:00

Embedding向量嵌入

2022-09-27 13:34:49

splice零拷貝原理

2023-12-06 07:28:47

阻塞IO異步IO

2022-04-12 08:00:17

socket 編程網(wǎng)絡(luò)編程網(wǎng)絡(luò) IO 模型

2023-09-22 12:21:33

Python深拷貝淺拷貝

2023-10-07 22:43:04

IO系統(tǒng)JAVA

2024-08-16 21:30:00

IO網(wǎng)絡(luò)網(wǎng)絡(luò)通信

2024-09-26 08:53:43

2024-04-12 12:19:08

語言模型AI

2025-03-31 08:50:00

模型量化神經(jīng)網(wǎng)絡(luò)AI

2022-03-24 08:51:48

Redis互聯(lián)網(wǎng)NoSQL

2023-05-09 11:13:09

IO模型語言

2023-07-29 13:45:30

了不起 Java極

2018-05-21 07:08:18

行為驅(qū)動(dòng)開發(fā)BDD編碼

2024-11-05 14:00:56

2021-03-22 10:05:59

netstat命令Linux

2023-09-08 08:20:46

ThreadLoca多線程工具

2023-09-15 12:00:01

API應(yīng)用程序接口

2020-11-12 09:14:25

JAVA.IO、字符編
點(diǎn)贊
收藏

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