一文詳解 I O 優化

2022-09-13 07:57:09 字數 3030 閱讀 3471

在沒有 dma 技術之前,i/o過程是這樣的:

cpu 發出對應的指令給磁碟控制器,飯後返回。

磁碟控制器收到指令後,於是就開始準備資料,會把資料放入到磁碟控制器的內部緩衝區中,然後產生乙個中斷。

cpu 收到中斷訊號後,停下手頭的工作,接著把磁碟控制器的緩衝區的資料一次乙個位元組地讀進自己的暫存器,然後再把暫存器裡的資料寫入到記憶體,而在資料傳輸的期間 cpu 是無法執行其他任務的。

可以看到整個資料傳輸的過程,都需要 cpu 親自參與搬運資料的過程,而且這個過程,cpu 是不能做其他事情的。如果我們用千兆網絡卡或者硬碟傳輸大量資料的時候,都用 cpu 來搬運的話,肯定忙不過來。

於是 dma 技術問世了,也就是直接記憶體訪問(direct memory access) 技術。

什麼是 dma 技術?就是在進行 i/o 裝置與記憶體的資料傳輸的時候,資料搬運的工作全部交給dma控制器,而 cpu 不再參與任何與資料搬運相關的事情,這樣 cpu 就可以去處理別的事務了。

使用 dma 控制器進行資料傳輸的過程如下:

注意:圖中的核心緩衝區就是上圖中的 pagecache

可以看到,整個傳輸資料的過程,cpu 不再參與資料搬運的工作,而是全稱由 dma 完成,但是 cpu 在這個過程中也是必不可少的,因為傳輸什麼資料,從**傳輸到**,都需要 cpu 來告訴 dma 控制器。

如果伺服器要提供檔案傳輸的功能,一般想到的就是將磁碟上的檔案讀取出來,然後通過網路協議傳送給客戶端。

傳統 i/o 的工作方式:資料讀取和寫入是從使用者空間到核心空間來回複製,而核心空間的資料是通過作業系統層面的 i/o 介面從磁碟讀取或寫入。

具體過程如下如所示:

首先,期間共發生了 4 次使用者態與核心態的上下文切換,上下文切換的成本並不小,在高併發的場景下,影響系統效能。還發生了 4 次資料拷貝,兩次是 dma拷貝,兩次是 cpu 拷貝。

我們只是搬運乙份資料,結果卻搬運了4次,過多的資料拷貝無疑會消耗 cpu 資源,大大降低了系統效能。

這種簡單又傳統的傳輸方式,存在冗餘的上下文切換和資料拷貝,在高併發系統裡是非常糟糕的,多了很多不必要的開銷,會嚴重影響系統效能。

所以,想要提高檔案傳輸的效能,就需要減少使用者態與核心態的上下文切換和記憶體拷貝的次數。

如何減少使用者態與核心態的上下文切換的次數呢?

讀取磁碟資料的時候,之所以要發生上下文切換,是因為使用者空間沒有許可權操作磁碟或網絡卡,核心的許可權最高,這些操作裝置的過程都需要交由作業系統核心來完成,所以一般要通過核心去完成某些任務的時候,就需要使用作業系統提供的系統呼叫函式。

而一次系統呼叫必然會發生 2 次上下文切換:首先從使用者態切換到核心態,當核心執行完任務後,再切換回使用者態交由程序**執行。

所以,要減少上下文切換的次數,就要減少系統呼叫的次數。

如何減少資料拷貝的次數?

傳統的檔案傳輸方式會歷經 4 次資料拷貝,而且這裡面,從核心的讀緩衝區拷貝到使用者的緩衝區裡,再從使用者的緩衝區拷貝到 socket 快取區,這個過程是沒有必要的。

因為檔案傳輸的應用場景中,在使用者空間我們並不會對資料再加工,所以資料實際上不用搬運到使用者空間,因此使用者的快取區是沒有必要存在的。

零拷貝技術實現的方式通常有2中:

mmap+write

前面我們知道,read()系統呼叫的過程中會把核心緩衝區的資料拷貝到使用者的緩衝區裡,於是為了減少這一步開銷,我們可以使用 mmap() 替換 read()系統呼叫函式。

mmap()系統呼叫會直接把核心緩衝區裡的資料對映到使用者空間,這樣,作業系統核心與使用者空間不需要再進行任何的資料拷貝操作。

具體過程如下:

這還不是最理想的零拷貝,仍然需要通過 cpu 把核心緩衝區的資料拷貝到 socket 緩衝區裡,仍然需要4次上下文切換,因為系統呼叫還是 2 次。

sendfile

在 linux 核心版本 2.1 中,提供了乙個專門傳送檔案的系統呼叫函式 sendfile(),它可以代替前面的 read()和 write()這兩個系統呼叫,這樣就可以減少一次系統呼叫,也就減少了2次上下文切換的開銷。

該系統呼叫可以直接把核心緩衝區裡的資料拷貝到 socket 緩衝區裡,不再拷貝到使用者態,這樣就只有2次上下文切換,和3次資料拷貝,如下圖:

但是這不是真正的零拷貝技術,如果網絡卡支援 sg-dma 技術,可以進一步減少通過 cpu 把核心緩衝區裡的資料拷貝到 socket 緩衝區的過程。於是從 linux 2.4 版本開始,對於網絡卡支援 sg-dma 技術的情況下,sendfile()系統呼叫的過程發生了點變化,具體過程如下:

這就是零拷貝技術,因為我們沒有在記憶體層面去拷貝資料,也就是說全稱沒有通過 cpu 來搬運資料,所有的資料都是通過 dma 來進行傳輸的。

零拷貝技術的檔案傳輸方式相比傳統的檔案傳輸方式,減少了 2 次上下文切換和資料拷貝次數,只需要 2 次上下文切換和資料拷貝過程,都不需要通過 cpu,2次都是有 dma 來搬運。

總體上看,零拷貝技術可以把檔案傳輸的效能提高至少一倍以上。

使用零拷貝的專案:

參考:小林coding**系統

一文詳解TCP協議

osi層 功能tcp ip協議 應用層文字傳輸,電子郵件,檔案服務,虛擬終端 ftp,http,snmp,dns等 表示層 資料格式化,轉換,資料加密 沒有協議 會話層 解除或建立與其他節點的聯絡 沒有協議 傳輸層提供端對端的介面 tcp,udp 網路層為資料報選擇路由 ip,icmp,rip,os...

一文詳解scp命令

加密的方式在本地主機和遠端主機之間複製檔案 scp命令用於在linux下進行遠端拷貝檔案的命令,和它類似的命令有cp,不過cp只是在本機進行拷貝不能跨伺服器,而且scp傳輸是加密的。可能會稍微影響一下速度。當你伺服器硬碟變為唯讀read only system時,用scp可以幫你把檔案移出來。另外,...

一文搞懂C 標準IO庫

介紹 分類普通流 檔案流介紹注意點 string流介紹 首先看一下io庫,標準函式庫,stl這些概念之間都是怎麼樣乙個關係 什麼是io庫?io庫就是有一些標準io類組成的類庫 通過這些io類可以實現對可實現對裝置 控制台,檔案等 的io操作,對記憶體的io 即string類 操作 其中對控制台的io...