DPDK記憶體(二)記憶體申請操作

2021-10-01 10:38:59 字數 2464 閱讀 7657

eal提供了乙個malloc api用於申請任意大小記憶體。

這個api的目的是提供類似malloc的功能,以允許從hugepage中分配記憶體並方便應用程式移植。

通常,這些型別的分配操作不應該在資料面處理中進行,因為他們比基於池的分配慢,並且在分配和釋放路徑中使用了鎖操作。但是,他們可以在配置**中使用。

當config_rte_malloc_debug開啟時,分配的記憶體包括保護字段,這個字段用於幫助識別緩衝區溢位。

介面rte_malloc()傳入乙個對齊引數,該引數用於請求在該值的倍數上對齊的記憶體區域(這個值必須是2的冪次)。

在支援numa的系統上,對rte_malloc()介面呼叫將返回在呼叫函式的core所在的插槽上分配的記憶體。dpdk還提供了另一組api,以允許在指定numa插槽上直接顯式分配記憶體,或者分配另乙個nuam插槽上的記憶體。

這個api旨在由初始化時需要類似malloc功能的應用程式呼叫。

需要在執行時分配/釋放資料,在應用程式的快速路徑中,應該使用記憶體池庫。

malloc庫中內部使用兩種資料結構型別:

struct malloc_heap:用於在每個插槽上跟蹤可用記憶體空間

struct malloc_elem:庫內部分配和釋放空間跟蹤的基本要素

資料結構malloc_heap用於管理每個插槽上的可用記憶體空間。在內部,每個numa節點有乙個堆結構,這允許我們根據此執行緒執行的numa節點為執行緒分配記憶體。雖然這並不能保證在numa節點上使用記憶體,但是它並不比記憶體總是在固定或隨機節點上的方案更糟。

堆結構及其關鍵字段和功能描述如下:

lock:需要鎖來同步對堆結構的訪問。假定使用鍊錶來跟蹤堆中的可用空間,我們需要乙個鎖

來防止多個執行緒同時處理該鍊錶。

free_head:指向這個malloc堆的空閒結點鍊錶中的第乙個元素。

資料結構malloc_elem用作各種記憶體塊的通用頭結構。 它以三種不同的方式使用,如上圖所示:

1.作為乙個釋放/申請記憶體的頭部,正常使用

2.作為記憶體塊內部填充頭

3.作為記憶體結尾標記

結構中重要的字段和使用方法如下所述:

1.heap:這個指標指向了該記憶體塊從哪個堆申請。它被用於正常的記憶體塊,當他們被釋放時,將新釋放的塊新增到堆的空閒列表中。

3.next_free:這個指標用於將空閒塊列表連線在一起。它用於正常的記憶體塊,在malloc() 介面中用於找到乙個合適的空閒塊申請出來,在free() 函式中用於將記憶體塊新增到空閒鍊錶。

5.pad:這個欄位為塊開始處的填充長度。在正常塊頭部情況下,它被新增到頭結構的結尾,以給出資料區的開始位址,即在malloc上傳回的位址。在填充虛擬頭部時,儲存相同的值,並從虛擬頭部的位址中減去實際塊頭部的位址。

6.size:資料塊的大小,包括頭部本身。對於結尾結構,這個大小需要指定為0,雖然從未使用。對於正在釋放的正常記憶體塊,使用此大小值替代 「next」 指標,以標識下乙個塊的儲存位置,在free情況下,可以合併兩個空閒塊。

在eal初始化時,所有memseg都將作為malloc堆的一部分進行設定。這個設定包括在busy狀態結束時放置乙個虛擬結構,如果啟用了config_rte_malloc_debug,它可能包含乙個哨兵值,並在開始時為每個memseg指定乙個適當的元素頭。然後將free元素新增到malloc堆的空閒鍊錶中。

當應用程式呼叫類似malloc功能的函式時,malloc函式將首先為呼叫執行緒索引lcore_config結構,並確定該執行緒的numa 節點。numa 節點將作為引數傳給heap_alloc()函式,用於索引malloc_heap 結構陣列。參與索引引數還有大小、型別、對齊方式和邊界引數。

函式heap_alloc()將掃瞄堆的空閒鍊錶,嘗試找到乙個適用於所請求的大小、對齊方式和邊界約束的記憶體塊。

當已經識別出合適的空閒元素時,將計算要返回給使用者的指標。緊跟在該指標之前的記憶體的快取記憶體行填充了乙個malloc_elem頭部。由於對齊和邊界約束,在元素的開頭和結尾可能會有空閒的空間,這將導致已下行為:

1.檢查尾隨空間。如果尾部空間足夠大,例如 > 128 位元組,那麼空閒元素將被分割。否則,僅僅忽略它(浪費空間)。

2.檢查元素開始處的空間。如果起始處的空間很小, <=128 位元組,那麼使用填充頭,這部分空間被浪費。但是,如果空間很大,那麼空閒元素將被分割。

從現有元素的末尾分配記憶體的優點是不需要調整空閒鍊錶,空閒鍊錶中現有元素僅調整大小指標,並且後面的元素使用 「prev」 指標重定向到新建立的元素位置。

要釋放記憶體,將指向資料區開始的指標傳遞給free函式。從該指標中減去malloc_elem結構的大小,以獲得記憶體塊元素頭部。如果這個頭部型別是pad,那麼進一步減去pad長度,以獲得整個塊的正確元素頭。

從這個元素頭中,我們獲得指向塊所分配的堆的指標及必須被釋放的位置,以及指向前乙個元素的指標,並且通過size 字段,可以計算下乙個元素的指標。 這意味著我們永遠不會有兩個相鄰的free 記憶體塊,因為他們總是會被合併成乙個大的塊。

C 記憶體申請 記憶體釋放

在初步學習c 時,遇到分配和釋放。下面進行個人的最簡短的總結 規則1 用malloc或new申請記憶體之後,應該立即檢查指標值是否為null。防止使用指標值為null的記憶體。規則2 不要忘記為陣列和動態記憶體賦初值。防止將未被初始化的記憶體作為右值使用。規則3 避免陣列或指標的下標越界,特別要當心...

Linux C幾種申請記憶體的操作

from c語言中文網 void malloc size t size 最常用贅述 void calloc size t numelements,size t sizeofoneelement 申請的記憶體區域會先清零,記憶體大小 numelements sizeofoneelement void ...

VC 記憶體申請

問題 如果要申請一塊記憶體?應該如何做?解答 在vc 一般的做法是 lpvoid pvdata 宣告乙個任何型別的指標 dword dwfilesize 申請記憶體的大小 分配全域性的可移動的記憶體 hglobal hglobal globalalloc gmem moveable,dwfilesi...