0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

詳解Linux系統(tǒng)中的零拷貝技術(shù)

書生途 ? 來源:書生途 ? 作者:書生途 ? 2022-05-18 09:18 ? 次閱讀

1.前言

Linux系統(tǒng)中一切皆文件,仔細(xì)想一下Linux系統(tǒng)的很多活動(dòng)無外乎讀操作寫操作,零拷貝就是為了提高讀寫性能而出現(xiàn)的。

2. 數(shù)據(jù)拷貝基礎(chǔ)過程

在Linux系統(tǒng)內(nèi)部緩存和內(nèi)存容量都是有限的,更多的數(shù)據(jù)都是存儲(chǔ)在磁盤中。對(duì)于Web服務(wù)器來說,經(jīng)常需要從磁盤中讀取數(shù)據(jù)到內(nèi)存,然后再通過網(wǎng)卡傳輸給用戶:

pYYBAGKDpOGAPJZfAAAcNVKnN_0687.jpg

上述數(shù)據(jù)流轉(zhuǎn)只是大框,接下來看看幾種模式。

2.1 僅CPU方式

  • 當(dāng)應(yīng)用程序需要讀取磁盤數(shù)據(jù)時(shí),調(diào)用read()從用戶態(tài)陷入內(nèi)核態(tài),read()這個(gè)系統(tǒng)調(diào)用最終由CPU來完成;
  • CPU向磁盤發(fā)起I/O請(qǐng)求,磁盤收到之后開始準(zhǔn)備數(shù)據(jù);
  • 磁盤將數(shù)據(jù)放到磁盤緩沖區(qū)之后,向CPU發(fā)起I/O中斷,報(bào)告CPU數(shù)據(jù)已經(jīng)Ready了;
  • CPU收到磁盤控制器的I/O中斷之后,開始拷貝數(shù)據(jù),完成之后read()返回,再從內(nèi)核態(tài)切換到用戶態(tài);
poYBAGKDpOGAX8wMAACBio1Wd8s482.jpg

2.2 CPU&DMA方式

CPU的時(shí)間寶貴,讓它做雜活就是浪費(fèi)資源。

直接內(nèi)存訪問(Direct Memory Access),是一種硬件設(shè)備繞開CPU獨(dú)立直接訪問內(nèi)存的機(jī)制。所以DMA在一定程度上解放了CPU,把之前CPU的雜活讓硬件直接自己做了,提高了CPU效率。

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

pYYBAGKDpOGAGC40AABrkKuhAc0439.jpg

有了DMA的參與之后的流程發(fā)生了一些變化:

poYBAGKDpOGATnstAAB-YLAEwi4057.jpg

最主要的變化是,CPU不再和磁盤直接交互,而是DMA和磁盤交互并且將數(shù)據(jù)從磁盤緩沖區(qū)拷貝到內(nèi)核緩沖區(qū),之后的過程類似。

“【敲黑板】無論從僅CPU方式和DMA&CPU方式,都存在多次冗余數(shù)據(jù)拷貝和內(nèi)核態(tài)&用戶態(tài)的切換。

我們繼續(xù)思考Web服務(wù)器讀取本地磁盤文件數(shù)據(jù)再通過網(wǎng)絡(luò)傳輸給用戶的詳細(xì)過程。

3.普通模式數(shù)據(jù)交互

一次完成的數(shù)據(jù)交互包括幾個(gè)部分:系統(tǒng)調(diào)用syscall、CPU、DMA、網(wǎng)卡、磁盤等。

pYYBAGKDpOKAY9-PAAAvmMfdVbo564.jpg

系統(tǒng)調(diào)用syscall是應(yīng)用程序和內(nèi)核交互的橋梁,每次進(jìn)行調(diào)用/返回就會(huì)產(chǎn)生兩次切換:

  • 調(diào)用syscall 從用戶態(tài)切換到內(nèi)核態(tài)
  • syscall返回 從內(nèi)核態(tài)切換到用戶態(tài)
poYBAGKDpOKAfo94AABa6xahwiA547.jpg

來看下完整的數(shù)據(jù)拷貝過程簡圖:

pYYBAGKDpOKAUWLFAACW-FRuHQI637.jpg

讀數(shù)據(jù)過程:

  • 應(yīng)用程序要讀取磁盤數(shù)據(jù),調(diào)用read()函數(shù)從而實(shí)現(xiàn)用戶態(tài)切換內(nèi)核態(tài),這是第1次狀態(tài)切換;
  • DMA控制器將數(shù)據(jù)從磁盤拷貝到內(nèi)核緩沖區(qū),這是第1次DMA拷貝;
  • CPU將數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到用戶緩沖區(qū),這是第1次CPU拷貝;
  • CPU完成拷貝之后,read()函數(shù)返回實(shí)現(xiàn)用戶態(tài)切換用戶態(tài),這是第2次狀態(tài)切換;

寫數(shù)據(jù)過程:

  • 應(yīng)用程序要向網(wǎng)卡寫數(shù)據(jù),調(diào)用write()函數(shù)實(shí)現(xiàn)用戶態(tài)切換內(nèi)核態(tài),這是第1次切換;
  • CPU將用戶緩沖區(qū)數(shù)據(jù)拷貝到內(nèi)核緩沖區(qū),這是第1次CPU拷貝;
  • DMA控制器將數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到socket緩沖區(qū),這是第1次DMA拷貝;
  • 完成拷貝之后,write()函數(shù)返回實(shí)現(xiàn)內(nèi)核態(tài)切換用戶態(tài),這是第2次切換;

綜上所述:

  • 讀過程涉及2次空間切換、1次DMA拷貝、1次CPU拷貝;
  • 寫過程涉及2次空間切換、1次DMA拷貝、1次CPU拷貝;

可見傳統(tǒng)模式下,涉及多次空間切換和數(shù)據(jù)冗余拷貝,效率并不高,接下來就該零拷貝技術(shù)出場了。

【文章福利】需要C/C++ Linux服務(wù)器架構(gòu)師學(xué)習(xí)資料點(diǎn)擊加群1106675687(資料包括C/C++,Linux,golang技術(shù),Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協(xié)程,DPDK,ffmpeg等)

poYBAGKDpOKACNgyAADNQFdFy4Q510.jpg

4. 零拷貝技術(shù)

4.1 出現(xiàn)原因

我們可以看到,如果應(yīng)用程序不對(duì)數(shù)據(jù)做修改,從內(nèi)核緩沖區(qū)到用戶緩沖區(qū),再從用戶緩沖區(qū)到內(nèi)核緩沖區(qū)。兩次數(shù)據(jù)拷貝都需要CPU的參與,并且涉及用戶態(tài)與內(nèi)核態(tài)的多次切換,加重了CPU負(fù)擔(dān)。

我們需要降低冗余數(shù)據(jù)拷貝、解放CPU,這也就是零拷貝Zero-Copy技術(shù)。

4.2 解決思路

目前來看,零拷貝技術(shù)的幾個(gè)實(shí)現(xiàn)手段包括:mmap+write、sendfile、sendfile+DMA收集、splice等。

pYYBAGKDpOKAJOWxAABA7v1ZNgw627.jpg

4.2.1 mmap方式

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

這樣就減少了一次用戶態(tài)和內(nèi)核態(tài)的CPU拷貝,但是在內(nèi)核空間內(nèi)仍然有一次CPU拷貝。

poYBAGKDpOKAU9GfAACk90sxlZ4568.jpg

mmap對(duì)大文件傳輸有一定優(yōu)勢,但是小文件可能出現(xiàn)碎片,并且在多個(gè)進(jìn)程同時(shí)操作文件時(shí)可能產(chǎn)生引發(fā)coredump的signal。

4.2.2 sendfile方式

mmap+write方式有一定改進(jìn),但是由系統(tǒng)調(diào)用引起的狀態(tài)切換并沒有減少。

sendfile系統(tǒng)調(diào)用是在 Linux 內(nèi)核2.1版本中被引入,它建立了兩個(gè)文件之間的傳輸通道。

sendfile方式只使用一個(gè)函數(shù)就可以完成之前的read+write 和 mmap+write的功能,這樣就少了2次狀態(tài)切換,由于數(shù)據(jù)不經(jīng)過用戶緩沖區(qū),因此該數(shù)據(jù)無法被修改。

pYYBAGKDpOKAcOlZAACFtkEmL5Y768.jpgpoYBAGKDpOKAIUeGAACFRHIPdfk833.jpg

從圖中可以看到,應(yīng)用程序只需要調(diào)用sendfile函數(shù)即可完成,只有2次狀態(tài)切換、1次CPU拷貝、2次DMA拷貝。

但是sendfile在內(nèi)核緩沖區(qū)和socket緩沖區(qū)仍然存在一次CPU拷貝,或許這個(gè)還可以優(yōu)化。

4.2.3 sendfile+DMA收集

Linux 2.4 內(nèi)核對(duì) sendfile 系統(tǒng)調(diào)用進(jìn)行優(yōu)化,但是需要硬件DMA控制器的配合。

升級(jí)后的sendfile將內(nèi)核空間緩沖區(qū)中對(duì)應(yīng)的數(shù)據(jù)描述信息(文件描述符、地址偏移量等信息)記錄到socket緩沖區(qū)中。

DMA控制器根據(jù)socket緩沖區(qū)中的地址和偏移量將數(shù)據(jù)從內(nèi)核緩沖區(qū)拷貝到網(wǎng)卡中,從而省去了內(nèi)核空間中僅剩1次CPU拷貝。

pYYBAGKDpOOAQIQjAACUW9WZcJg234.jpg

這種方式有2次狀態(tài)切換、0次CPU拷貝、2次DMA拷貝,但是仍然無法對(duì)數(shù)據(jù)進(jìn)行修改,并且需要硬件層面DMA的支持,并且sendfile只能將文件數(shù)據(jù)拷貝到socket描述符上,有一定的局限性。

4.2.4 splice方式

splice系統(tǒng)調(diào)用是Linux 在 2.6 版本引入的,其不需要硬件支持,并且不再限定于socket上,實(shí)現(xiàn)兩個(gè)普通文件之間的數(shù)據(jù)零拷貝。

poYBAGKDpOOANK5ZAACDaK62x48633.jpg

splice 系統(tǒng)調(diào)用可以在內(nèi)核緩沖區(qū)和socket緩沖區(qū)之間建立管道來傳輸數(shù)據(jù),避免了兩者之間的 CPU 拷貝操作。

pYYBAGKDpOOAOB1OAACKsPPKCIU836.jpg

splice也有一些局限,它的兩個(gè)文件描述符參數(shù)中有一個(gè)必須是管道設(shè)備。

5.本文小結(jié)

本文通過介紹數(shù)據(jù)交互的基本過程、傳統(tǒng)模式的缺點(diǎn),進(jìn)而介紹了零拷貝的一些實(shí)現(xiàn)方法。

零拷貝技術(shù)是非常底層且重要的讀寫優(yōu)化,對(duì)于服務(wù)并發(fā)能力的提升有很大幫助。

審核編輯:湯梓紅
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10698

    瀏覽量

    209328
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11123

    瀏覽量

    207892
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    深度解析Linux拷貝原理

    所謂「拷貝」描述的是計(jì)算機(jī)操作系統(tǒng)當(dāng)中,CPU不執(zhí)行將數(shù)據(jù)從一個(gè)內(nèi)存區(qū)域,拷貝到另外一個(gè)內(nèi)存區(qū)域的任務(wù)。通過網(wǎng)絡(luò)傳輸文件時(shí),這樣通??梢怨?jié)省 CPU 周期和內(nèi)存帶寬。
    發(fā)表于 03-01 14:39 ?2567次閱讀

    Linux LED子系統(tǒng)詳解

    Linux LED子系統(tǒng)詳解
    的頭像 發(fā)表于 06-10 10:37 ?1299次閱讀
    <b class='flag-5'>Linux</b> LED子<b class='flag-5'>系統(tǒng)</b><b class='flag-5'>詳解</b>

    Linux系統(tǒng)命令及其使用詳解

    Linux系統(tǒng)命令及其使用詳解
    發(fā)表于 08-20 13:38

    嵌入式Linux系統(tǒng)開發(fā)技術(shù)詳解——基于ARM

    嵌入式Linux系統(tǒng)開發(fā)技術(shù)詳解——基于ARM,一共6個(gè)部分,給大家參考
    發(fā)表于 06-24 21:19

    ARM嵌入式Linux系統(tǒng)開發(fā)詳解

    Linux技術(shù)的*發(fā)展,全部采用當(dāng)前最流行和穩(wěn)定的Linux發(fā)行版或者相關(guān)工具,是Linux愛好者學(xué)習(xí)Linux的好幫手?!?/div>
    發(fā)表于 09-14 08:57

    Linux拷貝命令

    Linux cp命令拷貝命令非常實(shí)用,cp命令可以將指定路徑下的文件(目錄)拷貝到(成)另一文件或目錄
    發(fā)表于 07-24 08:32

    RAID拷貝技術(shù)研究

    從實(shí)際測試和理論分析角度出發(fā),研究了采用拷貝技術(shù)對(duì)提高RAID性能的重要性.研究結(jié)果表明拷貝技術(shù)
    發(fā)表于 07-01 17:09 ?20次下載

    linux核心技術(shù)詳解

    很好的一本Linux技術(shù)詳解,值得一讀。
    發(fā)表于 11-09 17:35 ?5次下載

    Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解》第5章、Linux文件系統(tǒng)與設(shè)備文件系統(tǒng)

    Linux設(shè)備驅(qū)動(dòng)開發(fā)詳解》第5章、Linux文件系統(tǒng)與設(shè)備文件系統(tǒng)
    發(fā)表于 10-27 14:13 ?0次下載
    《<b class='flag-5'>Linux</b>設(shè)備驅(qū)動(dòng)開發(fā)<b class='flag-5'>詳解</b>》第5章、<b class='flag-5'>Linux</b>文件<b class='flag-5'>系統(tǒng)</b>與設(shè)備文件<b class='flag-5'>系統(tǒng)</b>

    Linux系統(tǒng)EXP命令詳解質(zhì)量匯總

    Linux系統(tǒng)EXP命令詳解質(zhì)量匯總
    發(fā)表于 05-14 09:35 ?1次下載

    深度解讀Linux的3種“拷貝”命令

    概述 Linux 下有 3 種“拷貝”,分別是 ln,cp,mv,這 3 個(gè)命令貌似都能 copy 出一個(gè)新的文件出來。 細(xì)心的小伙伴看到我給 “拷貝” 打上了雙引號(hào)?因?yàn)?Linux
    的頭像 發(fā)表于 05-28 15:35 ?3184次閱讀
    深度解讀<b class='flag-5'>Linux</b>的3種“<b class='flag-5'>拷貝</b>”命令

    深入理解Linux系統(tǒng)拷貝技術(shù)

    內(nèi)存拷貝是比較耗時(shí)操作,拷貝是常用優(yōu)化手段,今天分享的文章就是Linux系統(tǒng)
    的頭像 發(fā)表于 09-01 15:12 ?2951次閱讀

    傳統(tǒng)IO演化至拷貝的過程

    拷貝(Zero-Copy)用于在數(shù)據(jù)讀寫過程減少不需要的CPU拷貝,CPU就那么幾個(gè),減少它的負(fù)擔(dān)自然可以提高處理效率。數(shù)據(jù)傳輸有本地的文件拷貝
    的頭像 發(fā)表于 11-09 09:09 ?352次閱讀
    傳統(tǒng)IO演化至<b class='flag-5'>零</b><b class='flag-5'>拷貝</b>的過程

    什么是拷貝技術(shù)

    的應(yīng)用,經(jīng)常會(huì)發(fā)生這種問題,導(dǎo)致CPU都在做數(shù)據(jù)拷貝,沒有時(shí)間處理其他的應(yīng)用功能了,直接的感覺就是處理卡頓。 拷貝技術(shù) 針對(duì)這種問題,
    的頭像 發(fā)表于 11-27 16:20 ?376次閱讀
    什么是<b class='flag-5'>零</b><b class='flag-5'>拷貝</b><b class='flag-5'>技術(shù)</b>

    如何進(jìn)行拷貝性能測試

    TogetherROS?·Bot拷貝性能測試 我們使用TogetherROS?·Bot系統(tǒng)內(nèi)部集成的性能測試工具——performance_test,來評(píng)估下開啟
    的頭像 發(fā)表于 11-27 16:51 ?337次閱讀
    如何進(jìn)行<b class='flag-5'>零</b><b class='flag-5'>拷貝</b>性能測試