零拷貝原理

請叫我動感超人發表於2018-12-20

io讀寫的方式

  • 中斷
  • DMA

中斷方式

中斷方式的流程圖如下:

image

1.使用者程式發起資料讀取請求
2.系統排程為該程式分配cpu
3.cpu向io控制器(ide,scsi)傳送io請求
4.使用者程式等待io完成,讓出cpu
5.系統排程cpu執行其他任務
6.資料寫入至io控制器的緩衝暫存器
7.緩衝暫存器滿了向cpu發出中斷訊號
8.cpu讀取資料至記憶體

缺點:中斷次數取決於緩衝暫存器的大小

DMA : 直接記憶體存取

DMA方式的流程圖如下:

image

1.使用者程式發起資料讀取請求
2.系統排程為該程式分配cpu
3.cpu向DMA傳送io請求
4.使用者程式等待io完成,讓出cpu
5.系統排程cpu執行其他任務
6.資料寫入至io控制器的緩衝暫存器
7.DMA不斷獲取緩衝暫存器中的資料(需要cpu時鐘)
8.傳輸至記憶體(需要cpu時鐘)
9.所需的全部資料獲取完畢後向cpu發出中斷訊號

優點:減少cpu中斷次數,不用cpu拷貝資料

資料拷貝

下面展示了 傳統方式讀取資料後並通過網路傳送 所發生的資料拷貝:

image

1.一個read系統呼叫後,DMA執行了一次資料拷貝,從磁碟到核心空間
2.read結束後,發生第二次資料拷貝,由cpu將資料從核心空間拷貝至使用者空間
3.send系統呼叫,cpu發生第三次資料拷貝,由cpu將資料從使用者空間拷貝至核心空間(socket緩衝區)
4.send系統呼叫結束後,DMA執行第四次資料拷貝,將資料從核心拷貝至協議引擎
另外,這四個過程中,每個過程都發生一次上下文切換

  • 記憶體緩衝資料,主要是為了提高效能,核心可以預讀部分資料,當所需資料小於記憶體緩衝區大小時,將極大的提高效能。
  • 零拷貝是為了消除這個過程中冗餘的拷貝

零拷貝-sendfile

對應到java中 為FileChannel.transferTo(long position, long count, WritableByteChannel target) //將資料從檔案通道傳輸到了給定的可寫位元組通道
避免了第2,3步的資料拷貝,參考下圖:

image

1.DMA從拷貝至核心緩衝區
2.cpu將資料從核心緩衝區拷貝至核心空間(socket緩衝區)
3.DMA將資料從核心拷貝至協議引擎
4.這三個過程中共發生2次上下文切換,分別為發起讀取檔案和傳送資料
以上過程發生了三次資料拷貝,其中有一次為cpu完成
linux核心2.4以後,socket緩衝區做了調整,DMA帶收集功能,如下圖:
image

1.DMA從拷貝至核心緩衝區
2.將資料的位置和長度的資訊的描述符增加至核心空間(socket緩衝區)
3.DMA將資料從核心拷貝至協議引擎

零拷貝-mmap

對應到java中為MappedByteBuffer//檔案記憶體對映 資料不會複製到使用者空間,只在核心空間,與sendfile類似,但是應用程式可以直接操作該記憶體。

相關文章