傳統IO到零拷貝

2021-10-10 10:20:25 字數 2338 閱讀 6143

以read函式分析:

read函式從描述符為fd的當前檔案位置拷貝最多n個位元組到儲存器位置buf。返回-1表示乙個錯誤,而返回0表示eof,否則,返回值表示是實際串送位元組的數量。

在沒有dma時,read函式實際上會經過下邊的步驟

使用者程序呼叫read函式,使用者態切換成核心態,cpu傳送指令到磁碟控制器

磁碟控制器接收指令後,把資料放入磁碟控制器的內部緩衝區,產生乙個中斷。

cpu收到中斷指令後,把磁碟緩衝區的資料讀進自己的暫存器,然後把暫存器的資料寫入記憶體。核心態切換為使用者態。

cpu需要參與資料搬運過程,如果資料量大的話,太消耗cpu資源了。

由此,出現了dma技術。

先了解下什麼是dma

dma(直接記憶體訪問)direct memory access:在進行 i/o 裝置和記憶體的資料傳輸的時候,資料搬運的工作全部交給 dma 控制器。

同樣的read命令。

使用者程序呼叫read方法,cpu將請求發給dma.

dma將請求發給磁碟

磁碟控制器接收指令後,把資料放入磁碟控制器的內部緩衝區,產生乙個中斷。

dma 收到磁碟的訊號,將磁碟控制器緩衝區中的資料拷貝到核心緩衝區中.

當dma讀取足夠多的資料,就傳送中斷訊號給cpu

cpu 收到 dma 的訊號,知道資料已經準備好,於是將資料從核心拷貝到使用者空間,系統呼叫返回。

cpu不在參與資料搬運的工作,而是由dma完成。

以正常一次讀取磁碟檔案傳送資料為例,需要呼叫下列命令

read(file, tmp_buf, len);

write(socket, tmp_buf, len);

發生了4次使用者態和核心態的上下文切換(兩次呼叫都是:使用者態->核心態,核心完成任務後:核心態->使用者態),4次資料的拷貝(磁碟資料->作業系統核心緩衝區->使用者緩衝區->核心的socket的緩衝區->網絡卡的緩衝區)

檔案傳輸的效能

減少上下文切換次數(每一次系統呼叫,都會經過兩次上下文切換)

減少資料拷貝次數

優化方案

mmap+write

sendfile

buf = mma(file,len)

mmap函式會直接吧核心緩衝區裡的資料對映到使用者空間,作業系統不需要進行任何資料的拷貝操作

發生了4次使用者態和核心態的上下文切換(兩次呼叫都是:使用者態->核心態,核心完成任務後:核心態->使用者態),3次資料的拷貝(磁碟資料->作業系統核心緩衝區(應用程序和作業系統共享)->核心的socket的緩衝區->網絡卡的緩衝區)

linux核心版本2.1後

ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

前兩個引數分別是目的端和源端的檔案描述符,後面兩個引數是源端的偏移量和複製資料的長度,返回值是實際複製資料的長度。

發生了2次使用者態和核心態的上下文切換(一次呼叫),3次資料的拷貝(磁碟資料->作業系統核心緩衝區->核心的socket的緩衝區->網絡卡的緩衝區)

網絡卡支援 sg-dma技術,從 linux 核心 2.4 版本開始起支援

2次資料的拷貝(磁碟資料->作業系統核心緩衝區->網絡卡的緩衝區)

這就是零拷貝,2次上下問切換,2次資料拷貝,全是dma拷貝,沒有cpu拷貝。

當檔案傳輸時,第一步都是需要先把磁碟檔案資料拷貝待核心快取區(pagecache)

讀寫磁碟相比與讀寫記憶體速度慢太多了,所以要用讀寫磁碟替換為讀寫記憶體。

pagecache來快取最近被訪問的資料,當空間不足時淘汰最久未被訪問的快取。

pagecache使用可預讀功能

因為區域性性(剛訪問的資料,短時間內再次訪問的概率很高),所以快取到pagecache裡

pagecache來快取最近被訪問的資料,當空間不足時淘汰最久未被訪問的快取。

因為磁碟資料讀取時(通過磁頭旋轉到資料所在的扇區,然後開始順序讀取)。旋轉磁頭非常耗時。預讀功能(kafka順序讀寫,很快)

讀磁碟資料->先在pagecache找,找不到,再從磁碟中讀取,快取到pagecache。

pagecache被大檔案佔據,其他熱點小檔案無法使用pagecache,磁碟讀寫下降

pagecache沒有享受到快取帶來的好處,卻耗費了dma多拷貝到pagecache一次

非同步io,前半部分,核心向磁碟發起請求,不等資料就位,就返回;

後半部分,核心資料拷貝到緩衝區後,程序將接收到核心的通知,處理資料,繞開pagecache,直接io;

非同步io+直接io(繞過pagecache)。

傳統IO的特點

1傳統io 2 傳統io有兩種方式 1 單執行緒方式 這種方式的io是阻塞的,伺服器的serversocket只能為乙個客戶端socket服務,不能接收到新的客戶端socket連線 public static void main string args catch ioexception e pri...

IO程式設計 一 傳統IO程式設計

假設我們要實現乙個需求 客戶端每隔兩秒向服務端傳送一次資訊,服務端接收列印 首先我們需要乙個服務端乙個客戶端 服務端socketserver 服務端監聽8000埠.迴圈接收新的客戶端連線請求.同時列印客戶端傳送來的訊息 public class socketserver catch ioexcept...

零拷貝問題

零拷貝 定義 避免cpu將資料從一塊儲存空間拷貝到另乙個儲存空間的技術。通常用於網路檔案傳輸 以減少cpu消耗和記憶體頻寬的占用 減少使用者空間 使用者可操作的記憶體快取區域 和cpu核心空間 cpu核心可操作的記憶體快取和暫存器快取 的拷貝過程,減少使用者上下文和cpu核心上下文的切換,讓cpu解...