2011-07-03 20 views
36

我想了解memalign()posix_memalign()有什麼功能。閱讀可用的文檔沒有幫助。posix_memalign/memalign做什麼

有人能幫我理解它是如何工作的,它用於什麼?或者,也許提供一個使用示例?我想知道linux內存是如何工作的,我需要編寫自己的簡單內存池(低碎片堆)。

+1

當您說「需要」時,您是在談論一項家庭作業任務還是您對軟件的需求?如果是後者,我很懷疑。標準分配器在大多數負載下都是非常低的碎片。 –

回答

46

malloc爲您提供了一個可以進行任何對齊的內存塊(唯一的要求是它必須與實現支持的最大基元類型對齊),posix_memalign爲您提供了一塊保證有內存的塊請求的路線。

因此, posix_memalign(&p, 32, 128)將是一個128字節的內存塊,其起始地址保證是32的倍數。

這對於需要內存的各種低級操作(如使用SSE指令或DMA)很有用服從特定的對齊。

+14

'malloc'的結果不具有「任何」對齊。它保證適合系統上任何本地類型(int,long,double,structs等)。你認爲大對齊可能用於特殊目的是正確的,但對於絕大多數應用程序來說,malloc的結果是一致的。 –

+1

@John:你是對的;讓我改變我的措辭... –

+1

有沒有很好的理由更喜歡'posix_memalign'而不是'mmap',它分配對齊的內存? –

2

它是如何工作的,取決於實施。該函數的目的是給你一個n字節對齊的內存塊(塊的起始地址是n的乘法)。

9

malloc總是返回設置爲任何基本類型所需的最大對齊方式的內存。這允許malloc'內存存儲您可能需要的任何類型。我對posix_memalign的描述的理解是,它返回一個內存位置,其地址將是您指定爲對齊的任意倍數。

我不知道這會在編寫自定義內存池時有多麼有用,但我已經提供了一個如何實現這個功能的示例。與我的例子不同的是,任何分配爲malloc_aligned的東西都必須用free_aligned釋放;但是,使用posix_memalign您可以使用free

#include <stdlib.h> 
#include <stdio.h> 

void *malloc_aligned(size_t alignment, size_t bytes) 
{ 
    // we need to allocate enough storage for the requested bytes, some 
    // book-keeping (to store the location returned by malloc) and some extra 
    // padding to allow us to find an aligned byte. im not entirely sure if 
    // 2 * alignment is enough here, its just a guess. 
    const size_t total_size = bytes + (2 * alignment) + sizeof(size_t); 

    // use malloc to allocate the memory. 
    char *data = malloc(sizeof(char) * total_size); 

    if (data) 
    { 
     // store the original start of the malloc'd data. 
     const void * const data_start = data; 

     // dedicate enough space to the book-keeping. 
     data += sizeof(size_t); 

     // find a memory location with correct alignment. the alignment minus 
     // the remainder of this mod operation is how many bytes forward we need 
     // to move to find an aligned byte. 
     const size_t offset = alignment - (((size_t)data) % alignment); 

     // set data to the aligned memory. 
     data += offset; 

     // write the book-keeping. 
     size_t *book_keeping = (size_t*)(data - sizeof(size_t)); 
     *book_keeping = (size_t)data_start; 
    } 

    return data; 
} 

void free_aligned(void *raw_data) 
{ 
    if (raw_data) 
    { 
     char *data = raw_data; 

     // we have to assume this memory was allocated with malloc_aligned. 
     // this means the sizeof(size_t) bytes before data are the book-keeping 
     // which points to the location we need to pass to free. 
     data -= sizeof(size_t); 

     // set data to the location stored in book-keeping. 
     data = (char*)(*((size_t*)data)); 

     // free the memory. 
     free(data); 
    } 
} 

int main() 
{ 
    char *ptr = malloc_aligned(7, 100); 

    printf("is 5 byte aligned = %s\n", (((size_t)ptr) % 5) ? "no" : "yes"); 
    printf("is 7 byte aligned = %s\n", (((size_t)ptr) % 7) ? "no" : "yes"); 

    free_aligned(ptr); 

    return 0; 
} 
+0

感謝您的支持!非常有用的一段代碼作爲memalign的替代品,這在某種程度上仍然是從mingw中遺漏的。 – Bart

5

除了奧利的回答,我想指出一個更重要的問題。

在最近的x86體系結構中,緩存行是可以從內存獲取到緩存的最小數據量,爲64字節。假設你的結構大小是56字節,你有一大堆數組。當查找一個元素時,CPU需要發出2個內存請求(即使它位於緩存行中間,它也可能發出2個請求)。這對性能不利,因爲您必須等待內存,並且使用更多緩存,這最終會導致更高的緩存未命中率。在這種情況下,僅僅使用posix_memalign是不夠的,但是你應該將你的結構填充或壓縮到64字節的邊界。

有40字節的結構是隻是運氣不好:)

-4

Deffault的malloc返回指針是多重的8,它的平均分malloc的內存塊有8個字節,並在每個塊的開始檢查可用內存。有兩個問題的面孔。

較大的塊將浪費更多的內存,但較大的塊幫助C更快地找到空閒塊存儲器。 memalign可以改變這些塊的大小。如果要節省內存,請將塊大小減小到2或4.如果要使應用程序更快,請將塊大小增加到2。

+4

這是錯誤的和令人困惑的。 – jleahy

2

由於memalign已過時(ref:man page),這裏只介紹malloc()和posix_memalign()之間的區別。 malloc()是8字節對齊的(例如,對於RHEL 32位),但對於posix_memalign(),對齊是用戶可定義的。要知道這個的用法,或許一個很好的例子是使用mprotect()來設置內存屬性。要使用mprotect(),內存指針必須是PAGE對齊的。因此,如果您使用pagesize調用posix_memalign()作爲對齊方式,則返回的指針可以輕鬆地提交給mprotect()以設置可讀寫可執行屬性。 (例如,在將數據複製到內存指針之後,可以將其設置爲只讀屬性以防止它被修改)。 「malloc()」的返回指針不能在這裏使用。