Linux零拷貝之sendfile/splice

  sendfile/splice實現了真正意義上的零拷貝:CPU完全不需要參與數據的拷貝,應用層Java NIO爲開發人員提供了FileChannel.transferFrom()/transferTo()方法使用零拷貝。

sendfile

傳輸原理

  1. 用戶進程通過 sendfile() 函數向內核(kernel)發起系統調用,上下文從用戶態(user space)切換爲內核態(kernel space);
  2. CPU 利用 DMA 控制器將數據從主存或硬盤拷貝到內核空間(kernel space)的讀緩衝區(read buffer);
  3. CPU 把讀緩衝區(read buffer)的文件描述符(file descriptor)和數據長度拷貝到網絡緩衝區(socket buffer);
  4. 基於已拷貝的文件描述符(file descriptor)和數據長度,CPU 利用 DMA 控制器的 gather/scatter 操作直接批量地將數據從內核的讀緩衝區(read buffer)拷貝到網卡進行數據傳輸;
  5. 上下文從內核態(kernel space)切換回用戶態(user space),Sendfile 系統調用執行返回;
    在這裏插入圖片描述

適用場景

  sendfile適用於文件數據到網卡的傳輸過程,並且用戶程序對數據沒有修改的場景;

splice

傳輸原理

  1. 用戶進程通過 splice() 函數向內核(kernel)發起系統調用,上下文從用戶態(user space)切換爲內核態(kernel space);
  2. CPU 利用 DMA 控制器將數據從主存或硬盤拷貝到內核空間(kernel space)的讀緩衝區(read buffer);
  3. CPU 在內核空間的讀緩衝區(read buffer)和網絡緩衝區(socket buffer)之間建立管道(pipeline);
  4. CPU 利用 DMA 控制器將數據從網絡緩衝區(socket buffer)拷貝到網卡進行數據傳輸;
  5. 上下文從內核態(kernel space)切換回用戶態(user space),Splice 系統調用執行返回;
    在這裏插入圖片描述

適用場景

  splice適用於任意兩個文件描述符中傳輸數據(兩個文件描述符參數中有一個必須是管道設備),並且用戶程序對數據沒有修改的場景;

Java應用

  Java NIO的FileChannel.transferFrom()/transferTo()底層基於sendfile/splice,不僅可以進行網絡文件傳輸,還可以對本地文件實現零拷貝操作,示意圖如下所示:
在這裏插入圖片描述

參考:

  1. 支撐百萬併發的“零拷貝”技術,你瞭解嗎?
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章