posix_memalign/memalign做了什么

two*_*e88 49 c memory memory-pool

我正在努力了解功能memalign()和功能posix_memalign().阅读可用的文档没有帮助.

有人可以帮助我理解它是如何工作的以及它用于什么?或者,也许提供一个用法示例?

我试图了解linux内存是如何工作的,我需要编写自己的简单内存池(低碎片堆).

Oli*_*rth 61

然而,malloc为您提供了一块可以进行任何对齐的内存(唯一的要求是它必须与实现支持的最大基元类型对齐),posix_memalign为您提供一块保证具有请求对齐的内存.

因此,例如,结果posix_memalign(&p, 32, 128)将是一个128字节的内存块,其起始地址保证是32的倍数.

这对于需要遵循特定对齐的内存的各种低级操作(例如使用SSE指令或DMA)非常有用.

  • `malloc`的结果不仅仅是"任何"对齐.保证适当地对齐系统上的任何本机类型(int,long,double,structs等).你是正确的,更大的对齐可能用于特殊目的,但肯定对于绝大多数应用程序,malloc的结果是正确的. (16认同)
  • 是否有充分的理由更喜欢 `posix_memalign` 而不是 `mmap`,后者分配对齐的内存? (4认同)
  • @EliBendersky `posix_memalign` 通常会从堆中分配一个块,而 `mmap` 将始终进入操作系统。例如,如果你想分配许多缓存行对齐的内存块,那么`posix_memalign` 是更可取的。这与更喜欢 `malloc` 而非 `mmap` 的原因相同。 (2认同)

Nod*_*ode 10

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;
}
Run Code Online (Sandbox Code Playgroud)


tot*_*phu 8

除了Oli的回答,我想指出一个更重要的问题.

在最近的x86体系结构中,缓存行是64字节,它是从内存到缓存的最小数据量.假设您的结构大小为56个字节,那么您有大量的结构.当您查找一个元素时,CPU将需要发出2个内存请求(即使它位于缓存行的中间,它也可能发出2个请求).这对性能不利,因为您必须等待内存,并且使用更多缓存,这最终会提供更高的缓存未命中率.在这种情况下,仅使用posix_memalign是不够的,但是您应该将结构填充或压缩为64字节边界.

有40字节结构只是运气不好:)