什么posix_memalign / memalign做
我试图了解什么函数memalign()
和posix_memalign()
做。 阅读可用的文档没有帮助。
有人可以帮我理解它是如何工作的,它是用来做什么的? 或者,也许提供一个使用示例?
我想了解linux内存如何工作,我需要写我自己的简单内存池(低碎片堆)。
尽pipemalloc
为您提供了一个可以进行任何alignment的内存块(唯一的要求是它必须与实现支持的最大的基本typesalignment), posix_memalign
为您提供了一个保证有alignment请求的内存块。
因此,例如posix_memalign(&p, 32, 128)
将是一个128字节的内存块,其起始地址保证是32的倍数。
这对于各种低级操作(如使用SSE指令或DMA)非常有用,它需要遵循特定alignment的内存。
malloc
总是返回设置为任何基本types所需的最大alignment方式的内存。 这允许malloc
的内存来存储你可能需要的任何types。 我对posix_memalign
的描述的理解是,它返回一个内存位置,其地址将是您指定为alignment的任意倍数。
我不知道编写一个自定义的内存池会有多么有用,但我已经提供了一个如何实现这个function的例子。 不同的是我的例子,任何分配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; }
除了奥利的回答之外,我想指出一个更重要的问题。
在最近的x86体系结构中,caching行是可以从内存获取到caching的最小数据量,为64字节。 假设你的结构大小是56个字节,你有一大堆数组。 当查找一个元素时,CPU将需要发出2个内存请求(即使它位于caching线中间,它也可能发出2个请求)。 这对性能不利,因为您必须等待内存,并且使用更多caching,最终会导致更高的caching未命中率。 在这种情况下,仅使用posix_memalign是不够的,但是您应该将结构压缩或压缩到64字节边界。
有40个字节的结构只是不幸运:)
它是如何工作的是依赖于实现。 该函数的目的是给你一个n字节alignment的内存块(块的起始地址是n的一个乘法)。
由于memalign已经过时(ref:man page),这里只介绍malloc()和posix_memalign()之间的区别。 malloc()是8字节alignment的(例如,对于RHEL 32位),但对于posix_memalign(),alignment是用户可定义的。 要知道这个的使用,也许一个很好的例子是使用mprotect()来设置内存属性。 要使用mprotect(),内存指针必须是PAGEalignment的。 因此,如果以pagesize调用posix_memalign()作为alignment方式,则返回的指针可以轻松地提交给mprotect()以设置读写可执行属性。 (例如,将数据复制到内存指针后,可以将其设置为只读属性,以防止修改)。 “malloc()”的返回指针不能在这里使用。
Deffault malloc的返回指针是8的倍数,它意味着malloc拆分内存到块有8个字节,并在每个块开始时检查可用内存。 有两个问题的面孔。
较大的块将浪费更多的内存,但较大的块帮助C更快地find空闲块存储器。 memalign可以改变这些块是多大。 如果要节省内存,请将块大小减小到2或4.如果要使应用程序更快,请将块大小增加到2。