C#中的特性+反射
I/O主要為:網路IO(本質是socket檔案讀取)、磁碟IO
每次IO,都要經由兩個階段:
① 將資料從檔案先載入至核心記憶體空間(緩衝區),等待資料準備完成,時間較長
② 將資料從核心緩衝區複製到使用者空間的程序的記憶體中,時間較短
由上圖可知,經過兩個階段,共產生了四次資料拷貝,即使使用了DMA來處理了與硬體的通訊,CPU仍然需要處理兩次資料拷貝,與此同時,在使用者態與核心態也發生了多次上下文切換,無疑也加重了CPU負擔
而傳統的Linux 作業系統資料拷貝也是基於標準 I/O 介面進行的,即 I/O 操作會將資料在作業系統核心地址空間的緩衝區和應用程式地址空間定義的緩衝區之間進行傳輸。這樣做的好處就是,當後續請求的資料已經存放在作業系統的高速緩衝儲存器中,那麼就不需要再進行實際的物理磁碟 I/O 操作,可以減少磁碟 I/O 的操作。但是也還有一個問題,資料傳輸過程中的資料拷貝操作卻導致了極大的 CPU 開銷,限制了作業系統有效進行資料傳輸操作的能力
零拷貝應運而生
零拷貝:是一種避免cpu將資料從一塊儲存拷貝到另一塊儲存的技術,針對作業系統中的裝置驅動程式、檔案系統、網路協議堆疊衍生出各種零拷貝技術,避免讓CPU做大量的資料拷貝任務,核心驅動程式處理I/0資料環節減少不必要的拷貝,讓CPU解脫出來專注於別的任務,有效改善資料傳輸效能
優點:
① 避免作業系統核心緩衝區之間進行資料拷貝操作。
② 避免作業系統核心和使用者應用程式地址空間這兩者之間進行資料拷貝操作。
③ 使用者應用程式可以避開作業系統直接訪問硬體儲存。
④ 資料傳輸儘量讓 DMA 來做。
將多種操作結合在一起,將任務需要進行拷貝的資料先快取起來,避免不必要的系統呼叫和上下文切換,對資料進行處理儘量讓硬體來做
從2.1版核心開始,Linux引入了sendfile來簡化操作,sendfile系統呼叫利用DMA引擎將檔案內容拷貝到核心緩衝區去,然後將帶有檔案位置和長度資訊的緩衝區描述符新增socket緩衝區去,這一步不會將核心中的資料拷貝到socket緩衝區中,省去了read() 和write() 這兩個系統呼叫,DMA引擎會將核心緩衝區的資料拷貝到協議引擎中去,避免了最後一次拷貝,使用sendfile不僅減少了資料拷貝的次數,還減少了上下文切換,資料傳送始終只發生在kernel space