【深入淺出Linux】零拷貝技術(shù)sendfile

前言

在了解零拷貝之前淑蔚,我們先來(lái)看看標(biāo)準(zhǔn)的的I/O操作..

1.傳統(tǒng)IO的原理
標(biāo)準(zhǔn) I/O又被稱作緩存 I/O 灵迫,大多數(shù)文件系統(tǒng)的默認(rèn) I/O 操作都是緩存 I/O书幕。在 Linux 的緩存 I/O 機(jī)制中象迎,操作系統(tǒng)會(huì)將 I/O 的數(shù)據(jù)先被拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中香伴,然后才會(huì)從操作系統(tǒng)內(nèi)核的緩沖區(qū)拷貝到應(yīng)用程序的地址空間慰枕。

傳統(tǒng)IO的原理

緩存 I/O 有以下這些優(yōu)點(diǎn):

  • 緩存 I/O 使用了操作系統(tǒng)內(nèi)核緩沖區(qū),在一定程度上分離了應(yīng)用程序空間和實(shí)際的物理設(shè)備即纲。
  • 緩存 I/O 可以減少讀盤的次數(shù)具帮,從而提高性能。

當(dāng)應(yīng)用程序嘗試讀取某塊數(shù)據(jù)的時(shí)候,如果這塊數(shù)據(jù)已經(jīng)存放在了內(nèi)核的緩沖區(qū)中蜂厅,那么這塊數(shù)據(jù)就可以立即返回給應(yīng)用程序匪凡,而不需要經(jīng)過(guò)實(shí)際的物理讀盤操作。當(dāng)然掘猿,如果數(shù)據(jù)在應(yīng)用程序讀取之前并未被存放在內(nèi)核的緩沖區(qū)中病游,那么就需要先將數(shù)據(jù)從磁盤讀到頁(yè)緩存中去。

對(duì)于寫操作來(lái)說(shuō)稠通,應(yīng)用程序也會(huì)將數(shù)據(jù)先寫到內(nèi)核的緩沖區(qū)中去衬衬,數(shù)據(jù)是否被立即寫到磁盤上去取決于應(yīng)用程序所采用的寫操作機(jī)制:
如果用戶采用的是同步寫機(jī)制( synchronous writes ), 那么數(shù)據(jù)會(huì)立即被寫回到磁盤上,應(yīng)用程序會(huì)一直等到數(shù)據(jù)被寫完為止改橘;
如果用戶采用的是延遲寫機(jī)制( deferred writes )滋尉,那么應(yīng)用程序就完全不需要等到數(shù)據(jù)全部被寫回到磁盤,數(shù)據(jù)只要被寫到頁(yè)緩存中(內(nèi)核的緩沖區(qū))去就可以了飞主。在延遲寫機(jī)制的情況下狮惜,操作系統(tǒng)會(huì)定期地將放在頁(yè)緩存中的數(shù)據(jù)刷到磁盤上。與異步寫機(jī)制( asynchronous writes )不同的是碌识,延遲寫機(jī)制在數(shù)據(jù)完全寫到磁盤上的時(shí)候不會(huì)通知應(yīng)用程序碾篡,而異步寫機(jī)制在數(shù)據(jù)完全寫到磁盤上的時(shí)候是會(huì)返回給應(yīng)用程序的。所以延遲寫機(jī)制本身是存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)的丸冕,而異步寫機(jī)制則不會(huì)有這方面的擔(dān)心耽梅。

2.傳統(tǒng)IO的缺點(diǎn)
在緩存 I/O 機(jī)制中,DMA 方式可以將數(shù)據(jù)直接從磁盤讀到頁(yè)緩存中胖烛,或者將數(shù)據(jù)從頁(yè)緩存直接寫回到磁盤上,而不能直接在應(yīng)用程序地址空間和磁盤之間進(jìn)行數(shù)據(jù)傳輸诅迷,這樣的話佩番,數(shù)據(jù)在傳輸過(guò)程中需要在應(yīng)用程序地址空間和頁(yè)緩存之間進(jìn)行多次數(shù)據(jù)拷貝操作,這些數(shù)據(jù)拷貝操作所帶來(lái)的 CPU 以及內(nèi)存開(kāi)銷是非常大的罢杉。

當(dāng)然也可以采用直接 I/O 技術(shù)來(lái)滿足自緩存應(yīng)用程序( self-caching applications)的需求趟畏。
具體描述可以看這篇博客:Linux 中直接 I/O 機(jī)制的介紹

一.為什么需要零拷貝技術(shù)?

如今,很多網(wǎng)絡(luò)服務(wù)器都是基于客戶端 - 服務(wù)器這一模型的滩租。在這種模型中赋秀,客戶端向服務(wù)器端請(qǐng)求數(shù)據(jù)或者服務(wù);服務(wù)器端則需要響應(yīng)客戶端發(fā)出的請(qǐng)求律想,并為客戶端提供它所需要的數(shù)據(jù)猎莲。隨著網(wǎng)絡(luò)服務(wù)的逐漸普及,video 這類應(yīng)用程序發(fā)展迅速技即。當(dāng)今的計(jì)算機(jī)系統(tǒng)已經(jīng)具備足夠的能力去處理 video 這類應(yīng)用程序?qū)蛻舳怂斐傻闹刎?fù)荷著洼,但是對(duì)于服務(wù)器端來(lái)說(shuō),它應(yīng)付由 video 這類應(yīng)用程序引起的網(wǎng)絡(luò)通信量就顯得捉襟見(jiàn)肘了。而且身笤,客戶端的數(shù)量增長(zhǎng)迅速豹悬,那么服務(wù)器端就更容易成為性能瓶頸。而對(duì)于負(fù)荷很重的服務(wù)器來(lái)說(shuō)液荸,操作系統(tǒng)通常都是引起性能瓶頸的罪魁禍?zhǔn)渍胺稹Ee個(gè)例子來(lái)說(shuō),當(dāng)數(shù)據(jù)“寫”操作或者數(shù)據(jù)“發(fā)送”操作的系統(tǒng)調(diào)用發(fā)出時(shí)娇钱,操作系統(tǒng)通常都會(huì)將數(shù)據(jù)從應(yīng)用程序地址空間的緩沖區(qū)拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中去涤久。操作系統(tǒng)這樣做的好處是接口簡(jiǎn)單,但是卻在很大程度上損失了系統(tǒng)性能忍弛,因?yàn)檫@種數(shù)據(jù)拷貝操作不單需要占用 CPU 時(shí)間片响迂,同時(shí)也需要占用額外的內(nèi)存帶寬。

一般來(lái)說(shuō)细疚,客戶端通過(guò)網(wǎng)絡(luò)接口卡向服務(wù)器端發(fā)送請(qǐng)求蔗彤,操作系統(tǒng)將這些客戶端的請(qǐng)求傳遞給服務(wù)器端應(yīng)用程序,服務(wù)器端應(yīng)用程序會(huì)處理這些請(qǐng)求疯兼,請(qǐng)求處理完成以后然遏,操作系統(tǒng)還需要將處理得到的結(jié)果通過(guò)網(wǎng)絡(luò)適配器傳遞回去。

二.什么是零拷貝技術(shù)吧彪?

簡(jiǎn)單一點(diǎn)來(lái)說(shuō)待侵,零拷貝就是一種避免 CPU 將數(shù)據(jù)從一塊存儲(chǔ)拷貝到另外一塊存儲(chǔ)的技術(shù)。

零拷貝技術(shù)可以減少數(shù)據(jù)拷貝和共享總線操作的次數(shù)姨裸,消除傳輸數(shù)據(jù)在存儲(chǔ)器之間不必要的中間拷貝次數(shù)秧倾,從而有效地提高數(shù)據(jù)傳輸效率。

而且傀缩,零拷貝技術(shù)減少了用戶應(yīng)用程序地址空間和操作系統(tǒng)內(nèi)核地址空間之間因?yàn)樯舷挛那袚Q而帶來(lái)的開(kāi)銷那先。進(jìn)行大量的數(shù)據(jù)拷貝操作其實(shí)是一件簡(jiǎn)單的任務(wù),從操作系統(tǒng)的角度來(lái)說(shuō)赡艰,如果 CPU 一直被占用著去執(zhí)行這項(xiàng)簡(jiǎn)單的任務(wù)售淡,那么這將會(huì)是很浪費(fèi)資源的;如果有其他比較簡(jiǎn)單的系統(tǒng)部件可以代勞這件事情慷垮,從而使得 CPU 解脫出來(lái)可以做別的事情揖闸,那么系統(tǒng)資源的利用則會(huì)更加有效。

零拷貝技術(shù)的要點(diǎn):

  • 避免操作系統(tǒng)內(nèi)核緩沖區(qū)之間進(jìn)行數(shù)據(jù)拷貝操作料身。
  • 避免操作系統(tǒng)內(nèi)核和用戶應(yīng)用程序地址空間這兩者之間進(jìn)行數(shù)據(jù)拷貝操作汤纸。
  • 用戶應(yīng)用程序可以避開(kāi)操作系統(tǒng)直接訪問(wèn)硬件存儲(chǔ)。
  • 數(shù)據(jù)傳輸盡量讓 DMA 來(lái)做惯驼。

DMA:是指外部設(shè)備不通過(guò)CPU而直接與系統(tǒng)內(nèi)存交換數(shù)據(jù)的接口技術(shù)蹲嚣。

零拷貝技術(shù)分類
Linux 中的零拷貝技術(shù)主要有下面這幾種:

  • 直接 I/O
  • mmap
  • sendfile
  • splice

本文主要介紹sendfile這種零拷貝技術(shù)..

三.sendfile實(shí)現(xiàn)零拷貝的原理

1.描述
sendfile系統(tǒng)調(diào)用在兩個(gè)文件描述符之間直接傳遞數(shù)據(jù)(完全在內(nèi)核中操作)递瑰,從而避免了數(shù)據(jù)在內(nèi)核緩沖區(qū)和用戶緩沖區(qū)之間的拷貝,操作效率很高隙畜,被稱之為零拷貝抖部。

2.原理
sendfile() 系統(tǒng)調(diào)用利用 DMA 引擎將文件中的數(shù)據(jù)拷貝到操作系統(tǒng)內(nèi)核緩沖區(qū)中,然后數(shù)據(jù)被拷貝到與 socket 相關(guān)的內(nèi)核緩沖區(qū)中去议惰。接下來(lái)慎颗,DMA 引擎將數(shù)據(jù)從內(nèi)核 socket 緩沖區(qū)中拷貝到協(xié)議引擎中去。

sendfile() 系統(tǒng)調(diào)用不需要將數(shù)據(jù)拷貝或者映射到應(yīng)用程序地址空間中去言询,所以 sendfile() 只是適用于應(yīng)用程序地址空間不需要對(duì)所訪問(wèn)數(shù)據(jù)進(jìn)行處理的情況俯萎。因?yàn)?sendfile 傳輸?shù)臄?shù)據(jù)沒(méi)有越過(guò)用戶應(yīng)用程序 / 操作系統(tǒng)內(nèi)核的邊界線,所以 sendfile () 也極大地減少了存儲(chǔ)管理的開(kāi)銷运杭。

簡(jiǎn)單歸納上述的過(guò)程:

  • sendfile系統(tǒng)調(diào)用利用DMA引擎將文件數(shù)據(jù)拷貝到內(nèi)核緩沖區(qū)夫啊,之后數(shù)據(jù)被拷貝到內(nèi)核socket緩沖區(qū)中
  • DMA引擎將數(shù)據(jù)從內(nèi)核socket緩沖區(qū)拷貝到協(xié)議引擎中

這里沒(méi)有用戶態(tài)和內(nèi)核態(tài)之間的切換,也沒(méi)有內(nèi)核緩沖區(qū)和用戶緩沖區(qū)之間的拷貝辆憔,大大提升了傳輸性能撇眯。

四.帶有 DMA 收集拷貝功能的 sendfile

上面介紹的 sendfile() 技術(shù)在進(jìn)行數(shù)據(jù)傳輸仍然還需要一次多余的數(shù)據(jù)拷貝操作,通過(guò)引入一點(diǎn)硬件上的幫助虱咧,這僅有的一次數(shù)據(jù)拷貝操作也可以避免熊榛。為了避免操作系統(tǒng)內(nèi)核造成的數(shù)據(jù)副本,需要用到一個(gè)支持收集操作的網(wǎng)絡(luò)接口腕巡。主要的方式是待傳輸?shù)臄?shù)據(jù)可以分散在存儲(chǔ)的不同位置上玄坦,而不需要在連續(xù)存儲(chǔ)中存放。這樣一來(lái)绘沉,從文件中讀出的數(shù)據(jù)就根本不需要被拷貝到 socket 緩沖區(qū)中去煎楣,而只是需要將緩沖區(qū)描述符傳到網(wǎng)絡(luò)協(xié)議棧中去,之后其在緩沖區(qū)中建立起數(shù)據(jù)包的相關(guān)結(jié)構(gòu)梆砸,然后通過(guò) DMA 收集拷貝功能將所有的數(shù)據(jù)結(jié)合成一個(gè)網(wǎng)絡(luò)數(shù)據(jù)包转质。網(wǎng)卡的 DMA 引擎會(huì)在一次操作中從多個(gè)位置讀取包頭和數(shù)據(jù)。Linux 2.4 版本中的 socket 緩沖區(qū)就可以滿足這種條件帖世,這種方法不但減少了因?yàn)槎啻紊舷挛那袚Q所帶來(lái)開(kāi)銷,同時(shí)也減少了處理器造成的數(shù)據(jù)副本的個(gè)數(shù)沸枯。對(duì)于用戶應(yīng)用程序來(lái)說(shuō)日矫,代碼沒(méi)有任何改變。

主要過(guò)程如下:
首先绑榴,sendfile() 系統(tǒng)調(diào)用利用 DMA 引擎將文件內(nèi)容拷貝到內(nèi)核緩沖區(qū)去哪轿;然后,將帶有文件位置和長(zhǎng)度信息的緩沖區(qū)描述符添加到 socket 緩沖區(qū)中去翔怎,此過(guò)程不需要將數(shù)據(jù)從操作系統(tǒng)內(nèi)核緩沖區(qū)拷貝到 socket 緩沖區(qū)中窃诉,DMA 引擎會(huì)將數(shù)據(jù)直接從內(nèi)核緩沖區(qū)拷貝到協(xié)議引擎中去杨耙,這樣就避免了最后一次數(shù)據(jù)拷貝。

五.總結(jié)

上述的兩種幾種I/O操作對(duì)比:

1.傳統(tǒng)I/O
硬盤—>內(nèi)核緩沖區(qū)—>用戶緩沖區(qū)—>內(nèi)核socket緩沖區(qū)—>協(xié)議引擎

2.sendfile
硬盤—>內(nèi)核緩沖區(qū)—>內(nèi)核socket緩沖區(qū)—>協(xié)議引擎

3.sendfile( DMA 收集拷貝)
硬盤—>內(nèi)核緩沖區(qū)—>協(xié)議引擎


Tips:用戶態(tài)和內(nèi)核態(tài)切換的代價(jià)在哪飘痛?

首先珊膜,用戶態(tài)一個(gè)進(jìn)程,內(nèi)核態(tài)一個(gè)進(jìn)程宣脉,切換就要進(jìn)行進(jìn)程間的切換车柠。
拿系統(tǒng)調(diào)用舉例來(lái)說(shuō),系統(tǒng)調(diào)用一般都需要保存用戶程序得上下文(context), 在進(jìn)入內(nèi)核得時(shí)候需要保存用戶態(tài)得寄存器塑猖,在內(nèi)核態(tài)返回用戶態(tài)得時(shí)候會(huì)恢復(fù)這些寄存器得內(nèi)容竹祷。這是一個(gè)開(kāi)銷的地方。

如果需要在不同用戶程序間切換的話羊苟,那么還要更新cr3寄存器塑陵,這樣會(huì)更換每個(gè)程序的虛擬內(nèi)存到物理內(nèi)存映射表的地址,也是一個(gè)比較高負(fù)擔(dān)的操作蜡励。

而且內(nèi)核代碼對(duì)用戶不信任令花,需要進(jìn)行額外的檢查。系統(tǒng)調(diào)用的返回過(guò)程有很多額外工作巍虫,比如檢查是否需要調(diào)度等彭则。


六.參考資料

1、Linux 中直接 I/O 機(jī)制的介紹
2占遥、Linux 中的零拷貝技術(shù)俯抖,第 1 部分
3、Linux 中的零拷貝技術(shù)瓦胎,第 2 部分

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芬萍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子搔啊,更是在濱河造成了極大的恐慌柬祠,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件负芋,死亡現(xiàn)場(chǎng)離奇詭異漫蛔,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)旧蛾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門莽龟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人锨天,你說(shuō)我怎么就攤上這事毯盈。” “怎么了病袄?”我有些...
    開(kāi)封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵搂赋,是天一觀的道長(zhǎng)赘阀。 經(jīng)常有香客問(wèn)我,道長(zhǎng)脑奠,這世上最難降的妖魔是什么基公? 我笑而不...
    開(kāi)封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮捺信,結(jié)果婚禮上酌媒,老公的妹妹穿的比我還像新娘。我一直安慰自己迄靠,他們只是感情好秒咨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著掌挚,像睡著了一般雨席。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吠式,一...
    開(kāi)封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天陡厘,我揣著相機(jī)與錄音,去河邊找鬼特占。 笑死糙置,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的是目。 我是一名探鬼主播谤饭,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼懊纳!你這毒婦竟也來(lái)了揉抵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗤疯,失蹤者是張志新(化名)和其女友劉穎冤今,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體茂缚,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡戏罢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脚囊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帖汞。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凑术,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情所意,我是刑警寧澤淮逊,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布催首,位于F島的核電站,受9級(jí)特大地震影響泄鹏,放射性物質(zhì)發(fā)生泄漏郎任。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一备籽、第九天 我趴在偏房一處隱蔽的房頂上張望舶治。 院中可真熱鬧,春花似錦车猬、人聲如沸霉猛。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惜浅。三九已至,卻和暖如春伏嗜,著一層夾襖步出監(jiān)牢的瞬間坛悉,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工承绸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留裸影,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓军熏,卻偏偏與公主長(zhǎng)得像轩猩,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子羞迷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354