白話零拷貝

sendfile()這個系統調用 是在兩個文件描述符之間直接傳遞數據(這個操作是完全在內核態進行),從而避免了數據在內核緩衝區和用戶緩衝區之間的拷貝,稱之爲零拷貝,操作效率很高

--------------------------- 下面我們一步一步來了解什麼是零拷貝 -----------------------

我們知道I/O操作分爲緩存I/O和直接I/O

緩存I/O

緩存I/O,即標準I/O也就是傳統I/O;傳統IO在read時先把IO的數據拷貝到內核緩衝區,在拷貝到(用戶空間)應用程序緩衝區;write時再把用戶緩衝區的數據拷貝的內核緩衝區,如果數據是要通過網卡發送出去,數據還要從內核緩衝區再拷貝到網卡設備的緩衝區。一共經過了4次數據的拷貝
在這裏插入圖片描述
那麼傳統I/O好處:
1)內核緩衝區,在一定程度上將應用程序地址空間與時間物理設備隔離
2)可以減少讀磁盤的次數,當數據已經在緩衝區時,不需要進行實際的物理讀盤操作

對於寫操作:
synchronous writes同步寫機制:數據在寫入內核緩衝區後,會立即寫入磁盤,應用程序會一直等到數據寫完爲止
deferred writes延遲寫機制:只要數據寫到液緩存(即內核緩衝區)去就可以了,操作系統會定期的寫入磁盤。與asynchronous writes異步機制不同的一點就是,異步寫在完全寫入磁盤後會通知應用程序。而延遲寫不會,所以延遲寫是有可能會丟失數據的

傳統IO缺點:
傳統I/O 機制中,雖然有DMA 方式可以將數據直接從磁盤讀到頁緩存(即內核緩存)中,或者將數據從頁緩存直接寫回到磁盤上,但是DMA不能直接在應用程序地址空間和磁盤之間進行數據傳輸,這樣的話,數據在傳輸過程中需要在應用程序地址空間和頁緩存之間進行多次數據拷貝操作,這些數據拷貝操作所帶來的 CPU 以及內存開銷是非常大的。

在這裏插入圖片描述
直接I/O 如圖,直接I/O,可以直接把數據從一個設備發送到另一個設備,而不需要在內核緩衝區和用戶緩衝區直接把數據進行多次拷貝。直接I/O就沒有數據的拷貝,所以直接I/O也叫零拷貝

當應用程序因爲讀寫或者發送數據而使用系統調用(函數)時,就會發生用戶空間到內核空間的來回切換,來進行多次的數據複製,雖然系統調用接口很簡單。但這回損失系統的性能。這種簡單的數據拷貝 不單單要佔用CPU的時間片,還會佔用內存帶寬。而CPU和內容這都是最寶貴的系統資源,明顯很不划算。

而零拷貝避免了這種情況。
1 零拷貝沒有操作系統內核緩衝區之間進行數據拷貝
2 儘量避免內核緩衝區與應用程序緩衝區數據拷貝(除非這些數據需要應用程序進行處理,而不得不進行交互)
3 儘量使用DMA接口技術進行數據傳輸
一句話總結零拷貝就是不用進行數據拷貝,而直接進行數據傳輸的I/O操作,即直接I/O

---------------------- 下面看一下sendfile函數實現零拷貝的原理 ----------------------

簡單來說就是:
1)sendfile系統調用 利用DMA引擎將文件數據拷貝到內核緩衝區
2)之後數據被拷貝到內核socket緩衝區中,
3)DMA引擎將數據從內核socket緩衝區拷貝到協議引擎中,,這裏有一個默認前提是sendfile() 只是適用於應用程序地址空間不需要對所訪問數據進行處理的情況,因爲sendfile 操作的數據沒有在用戶程序地址空間和內核空間進行任何交互。

如果我們在硬件上在做一下改進,上面提到的一次到內核緩衝區的拷貝也可以避免。現在的linux系統其實通過DMA數據收集技術已經實現了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章