網絡卡的零拷貝理解

2021-08-23 12:08:24 字數 2630 閱讀 3011

**:

jack:最近聽說了網路處理的「零拷貝」技術,覺得非常神奇,在網上查閱了很多資料。不過,並不是太明白——知其然,而不知其所以然。你能通俗地解釋一下嗎?

我:這是乙個相對比較複雜的話題,說起來話就多了。本質上來說,其實就是80386的分頁管理變異而已。

jack:分頁管理?這個跨度有點大,穿越了。

我:你覺得穿越,是因為你基礎不過關。基礎不過關,看技術就像看天書。如果你「本源技術」學得很好,那些看是玄妙的技巧,一眼就可以看破

jack:為什麼說「零拷貝」技術的本質是80386的分頁管理變異的呢?

我:我們先說一說,零拷貝技術的本質是什麼吧。當乙個網路資料報通過網絡卡進入核心,然後再進入使用者空間的時候,至少會經過2次data copy。不要小看兩次data copy——網際網路行業的網路伺服器的cpu資源80%都消耗在這2次資料copy上去了,基本上別的事情都做不了。而事實上,這樣的資料拷貝完全是沒有必要的——這個資料報從網絡卡到核心再到使用者空間,這個拷貝的過程僅僅起到了「傳輸」的作用,而資料報內容沒有任何變化。零拷貝技術正是解決這兩次拷貝。它能讓兩次拷貝完全消除,一次都不拷貝。

jack:消除這兩次拷貝的關鍵點在**呢?

我:這裡需要分開討論。第一次資料拷貝發生在「網絡卡到核心」。網絡卡到核心這種說法算是比較邊緣性的。專業一點的說法是,外部裝置到主儲存器的資料傳輸。這個概念聽著熟悉吧?

jack:是的。這讓我想起了外部裝置到主存的三種資料傳輸方式——輪詢、中斷、dma。其中輪詢太齪了,基本上沒有實用價值,而dma適合在資料傳輸比較大的情況下使用,而且需要該外部裝置支援。一般情況下,中斷的方式用得比較多。

我:是的。中斷是作業系統的神經中樞。不過,如果要實現零拷貝技術,這個網絡卡一定要採用dma技術。

jack:為什麼呢?即便採用了dma技術,資料任然要從網絡卡拷貝到主存,並不能算作「零拷貝」。

我:是的。使用dma技術,仍然需要把資料從網絡卡拷貝到主存——但是,拷貝的過程中,cpu是完全不需要參與的。既然cpu不參與,就不會有任何cpu資源消耗,data copy帶來的損耗就可以避免開了,所以這一層的data copy就被cut了

jack:明白了。那核心到使用者空間的資料拷貝是怎麼消除的呢?

我:我先不回答這乙個問題。我先問乙個問題,資料如何從核心拷貝到使用者空間呢?

jack:從cpu層面來說,核心與使用者空間處於不同的段(segment),段間資料拷貝,必須要有乙個起中轉作用的段暫存器參與才行。

我:是的。386cpu有fs暫存器充當這樣的角色。

jack:但是,如何才能實現段間資料共享呢?

我:從cpu的記憶體管理的角度來說,這是不可能實現的。intel的設計就是段與段間分隔開來,每個段有自己的儲存空間、屬性等。

jack:那從cpu的記憶體管理的角度來說,「零拷貝」豈不是完全不能實現?

我:是的。不僅不能實現,「零拷貝」的思想與作業系統核心的設計思想、cpu的設計思想是完全背道而馳的,屬於妖孽那一類。

jack:不要賣關子了。直接說吧,linux核心是如何做到「零拷貝」的呢?

我:消除從linux核心到使用者空間的資料拷貝的關鍵點在於80386的虛擬記憶體機制——這是cpu層面的技術,並不是作業系統層面的技術。從linux核心的設計角度來講,它天生就認為從網絡卡到核心到使用者空間的2次資料拷貝是必須的,拷貝了兩次才是完整的(儘管做了無用功、在網路流量比較大的情況下效能低下,但是站在linux核心的角度,它就要這麼做)。而「零拷貝」技術正是打破了作業系統的設計理念,妖孽了一把,從cpu層面打破linux核心與使用者空間的阻隔,使其記憶體共享

jack:cpu的這種功能具體是什麼呢?

我:就是80386的虛擬記憶體管理與分頁機制的組合。虛擬記憶體可以通過頁目錄、頁表對映到物理記憶體位址,也可以直接對映到物理磁碟上(的檔案)去。關鍵點就在這裡了。既然虛擬記憶體可以對映到檔案上去,而檔案又是多個程序共享的(不用區分核心與使用者程序),核心的某一塊記憶體區域對映到乙個檔案,而使用者程序(server程序)又關聯到這乙個檔案,那麼這個使用者程序(server程序)就可以直接操作linux核心的某塊記憶體區域了。如果核心中的這塊記憶體區域再被設定為網絡卡dma對映的記憶體區,「零拷貝」也就實現了。

jack:linux為這種作業系統設計了api嗎?

我:有的。mmap()就是做這個事兒的。而實際上,unix程序間通訊的「共享記憶體」方式,其本質原理,也是這個。

jack:明白了,作為乙個作業系統核心,其設計理念勢必把核心與使用者程序區分開來,而各個使用者程序的記憶體區域也必然是互相隔離的。這樣,才是真正的程序的概念。程序間需要通訊,最「正當」的方式是在核心區域構建相應的資料結構,某程序需要通訊就通過系統呼叫進入核心區域,修改**,然後通知到需要通訊的程序。被通知的程序通過系統呼叫進入核心空間,通訊完成。如果程序間需要進行資料傳輸,只能先通過a程序傳輸到核心,然後再從核心傳輸到b程序,期間必然發生至少2次資料拷貝

我:是的。

jack:但是。「共享記憶體」mmap本質上借用了80386的虛擬記憶體管理模式,打破了作業系統的設計思想。而mmap其實是共享記憶體的一般使用模式

我:是的。能說出「而mmap其實是共享記憶體的一般使用模式」這樣的話,說明你把握到關鍵點了。

網絡卡的零拷貝理解

jack 最近聽說了網路處理的 零拷貝 技術,覺得非常神奇,在網上查閱了很多資料。不過,並不是太明白 知其然,而不知其所以然。你能通俗地解釋一下嗎?我 這是乙個相對比較複雜的話題,說起來話就多了。本質上來說,其實就是80386的分頁管理變異而已。jack 分頁管理?這個跨度有點大,穿越了。我 你覺得...

網絡卡驅動記憶體零拷貝技術

網絡卡驅動記憶體零拷貝技術實現思路 主要有這麼幾點 1.在核心中為rx分配一片連續的記憶體,再分割成乙個個的小buffer掛到descriptor上 由於linux核心分配大的記憶體塊有限制,所以可以分配幾大塊然後分別掛在descriptor上 2.把記憶體的實體地址傳給使用者空間的收包api.3....

零拷貝問題

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