CPU 全程負(fù)責(zé)內(nèi)存內(nèi)的數(shù)據(jù)拷貝還可以接受,因?yàn)樾蔬€算可以接受,但是如果要全程負(fù)責(zé)內(nèi)存與磁盤、網(wǎng)絡(luò)的數(shù)據(jù)拷貝,這將難以接受,因?yàn)榇疟P、網(wǎng)卡的速度遠(yuǎn)小于內(nèi)存,內(nèi)存又遠(yuǎn)遠(yuǎn)小于 CPU;
4 次 copy 太多了,4 次上下文切換也太頻繁了。
DMA 參與下的數(shù)據(jù)四次拷貝
DMA 技術(shù)很容易理解,本質(zhì)上,DMA 技術(shù)就是我們?cè)谥靼迳戏乓粔K獨(dú)立的芯片。在進(jìn)行內(nèi)存和 I/O 設(shè)備的數(shù)據(jù)傳輸?shù)臅r(shí)候,我們不再通過 CPU 來控制數(shù)據(jù)傳輸,而直接通過 DMA 控制器(DMA Controller,簡稱 DMAC)。這塊芯片,我們可以認(rèn)為它其實(shí)就是一個(gè)協(xié)處理器(Co-Processor)。 DMAC 最有價(jià)值的地方體現(xiàn)在,當(dāng)我們要傳輸?shù)臄?shù)據(jù)特別大、速度特別快,或者傳輸?shù)臄?shù)據(jù)特別小、速度特別慢的時(shí)候。 比如說,我們用千兆網(wǎng)卡或者硬盤傳輸大量數(shù)據(jù)的時(shí)候,如果都用 CPU 來搬運(yùn)的話,肯定忙不過來,所以可以選擇 DMAC。而當(dāng)數(shù)據(jù)傳輸很慢的時(shí)候,DMAC 可以等數(shù)據(jù)到齊了,再發(fā)送信號(hào),給到 CPU 去處理,而不是讓 CPU 在那里忙等待。 注意,這里面的“協(xié)”字。DMAC 是在“協(xié)助”CPU,完成對(duì)應(yīng)的數(shù)據(jù)傳輸工作。在 DMAC 控制數(shù)據(jù)傳輸?shù)倪^程中,我們還是需要 CPU 的進(jìn)行控制,但是具體數(shù)據(jù)的拷貝不再由 CPU 來完成。 原本,計(jì)算機(jī)所有組件之間的數(shù)據(jù)拷貝(流動(dòng))必須經(jīng)過 CPU,如下圖所示:
現(xiàn)在,DMA 代替了 CPU 負(fù)責(zé)內(nèi)存與磁盤以及內(nèi)存與網(wǎng)卡之間的數(shù)據(jù)搬運(yùn),CPU 作為 DMA 的控制者,如下圖所示:
但是 DMA 有其局限性,DMA 僅僅能用于設(shè)備之間交換數(shù)據(jù)時(shí)進(jìn)行數(shù)據(jù)拷貝,但是設(shè)備內(nèi)部的數(shù)據(jù)拷貝還需要 CPU 進(jìn)行,例如 CPU 需要負(fù)責(zé)內(nèi)核空間數(shù)據(jù)與用戶空間數(shù)據(jù)之間的拷貝(內(nèi)存內(nèi)部的拷貝),如下圖所示:
什么是零拷貝技術(shù)? 零拷貝技術(shù)是一個(gè)思想,指的是指計(jì)算機(jī)執(zhí)行操作時(shí),CPU 不需要先將數(shù)據(jù)從某處內(nèi)存復(fù)制到另一個(gè)特定區(qū)域。 可見,零拷貝的特點(diǎn)是 CPU 不全程負(fù)責(zé)內(nèi)存中的數(shù)據(jù)寫入其他組件,CPU 僅僅起到管理的作用。但注意,零拷貝不是不進(jìn)行拷貝,而是 CPU 不再全程負(fù)責(zé)數(shù)據(jù)拷貝時(shí)的搬運(yùn)工作。如果數(shù)據(jù)本身不在內(nèi)存中,那么必須先通過某種方式拷貝到內(nèi)存中(這個(gè)過程 CPU 可以不參與),因?yàn)閿?shù)據(jù)只有在內(nèi)存中,才能被轉(zhuǎn)移,才能被 CPU 直接讀取計(jì)算。 零拷貝技術(shù)的具體實(shí)現(xiàn)方式有很多,例如:
“直接”在這里還有另一層語義:其他所有技術(shù)中,數(shù)據(jù)至少需要在內(nèi)核空間存儲(chǔ)一份,但是在 Direct I/O 技術(shù)中,數(shù)據(jù)直接存儲(chǔ)在用戶空間中,繞過了內(nèi)核。 Direct I/O 模式如下圖所示: Direct I/O 示意圖 此時(shí)用戶空間直接通過 DMA 的方式與磁盤以及網(wǎng)卡進(jìn)行數(shù)據(jù)拷貝。 Direct I/O 的讀寫非常有特點(diǎn):
另一方面,目前 Linux 上的異步 IO 庫,其依賴于文件使用 O_DIRECT 模式打開,它們通常一起配合使用。 如何使用 Direct I/O? 用戶應(yīng)用需要實(shí)現(xiàn)用戶空間內(nèi)的緩存區(qū),讀/寫操作應(yīng)當(dāng)盡量通過此緩存區(qū)提供。如果有性能上的考慮,那么盡量避免頻繁地基于 Direct I/O 進(jìn)行讀/寫操作。