C语言 posix_memalign/memalign 有什么作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6563120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What does posix_memalign/memalign do
提问by artyomboyko
I'm trying to understand what functions memalign()and posix_memalign()do. Reading the available documentation didn't help.
我试图了解什么功能memalign()和posix_memalign()做什么。阅读可用的文档没有帮助。
Can someone help me understand how it works and what is it used for? Or, perhaps provide a usage example?
有人可以帮助我了解它的工作原理以及它的用途吗?或者,也许提供一个使用示例?
I'm trying to understand how linux memory works, I need to write my own simple memory pool (low-fragmentation heap).
我试图了解 linux 内存是如何工作的,我需要编写自己的简单内存池(低碎片堆)。
回答by Oliver Charlesworth
Whereas mallocgives you a chunk of memory that could have any alignment (the only requirement is that it must be aligned for the largest primitive type that the implementation supports), posix_memaligngives you a chunk of memory that is guaranteed to have the requested alignment.
而malloc给你一块可以有任何对齐的内存(唯一的要求是它必须为实现支持的最大原始类型对齐),posix_memalign给你一块保证具有请求对齐的内存。
So the result of e.g. posix_memalign(&p, 32, 128)will be a 128-byte chunk of memory whose start address is guaranteed to be a multiple of 32.
因此 eg 的结果posix_memalign(&p, 32, 128)将是一个 128 字节的内存块,其起始地址保证是 32 的倍数。
This is useful for various low-level operations (such as using SSE instructions, or DMA), that require memory that obeys a particular alignment.
这对于需要遵守特定对齐方式的内存的各种低级操作(例如使用 SSE 指令或 DMA)非常有用。
回答by Node
mallocalways returns memory that is set to the maximum alignment required by any of the primitive types. This allows malloc'd memory to store any type you may need. My understanding of the description of posix_memalign, is that it returns a memory location who's address will be a multiple of whatever you specify as the alignment.
malloc始终返回设置为任何基本类型所需的最大对齐的内存。这允许malloc'd 内存存储您可能需要的任何类型。我对 , 的描述的理解posix_memalign是它返回一个内存位置,其地址将是您指定为对齐方式的倍数。
Im not sure how useful this would be when writing a custom memory pool, but I have had a go at providing an example of how this could be implemented. The difference is with my example, anything allocated with malloc_alignedhas to be freed with free_aligned; however, with posix_memalignyou can use free.
我不确定在编写自定义内存池时这会有多大用处,但我已经尝试提供一个如何实现的示例。不同之处在于我的例子,任何分配的东西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;
}
回答by tothphu
In addition to Oli's answer I would like to point you to an even more important issue.
除了 Oli 的回答之外,我还想向您指出一个更重要的问题。
On recent x86 architectures a cache-line, which is the smallest amount of data that can fetched from memory to cache, is 64 bytes. Suppose your structure size is 56 bytes, you have a large array of them. When you lookup one element, the CPU will need to issue 2 memory requests (it might issue 2 requests even if it is in the middle of the cacheline). That is bad for performance, as you have to wait for memory, and you use more cache, which ultimately gives a higher cache-miss ratio. In this case it is not enough to just use posix_memalign, but you should pad or compact your structure to be on 64byte boundaries.
在最近的 x86 体系结构中,缓存行是 64 字节,它是可以从内存获取到缓存的最小数据量。假设您的结构大小为 56 字节,您有一个很大的数组。当您查找一个元素时,CPU 将需要发出 2 个内存请求(即使它位于缓存行的中间,它也可能发出 2 个请求)。这对性能不利,因为您必须等待内存,并且使用更多缓存,这最终会导致更高的缓存未命中率。在这种情况下,仅使用 posix_memalign 是不够的,但您应该将结构填充或压缩到 64 字节边界。
Having 40 byte struct is just bad luck :)
拥有 40 字节的结构只是运气不好:)
回答by MByD
How does it work is implementation dependent. The purpose of the function is to give you an n-bytes aligned memory block (the start address of the block is a multiply of n).
它如何工作取决于实现。该函数的目的是为您提供一个 n 字节对齐的内存块(该块的起始地址是 n 的乘积)。
回答by Peter Teoh
As memalign is obsolete (ref: man page), only the difference between malloc() and posix_memalign() will be described here. malloc() is 8-byte aligned (eg, for RHEL 32-bit), but for posix_memalign(), alignment is user-definable. To know the use of this, perhaps one good example is setting memory attribute using mprotect(). To use mprotect(), the memory pointer must be PAGE aligned. And so if you call posix_memalign() with pagesize as the alignment, then the returned pointer can easily submit to mprotect() to set the read-write-executable attributes. (for example, after you copy the data into the memory pointer, you can set it to read-only attribute to protect it from being modified). "malloc()"'s returned pointer cannot be use here.
由于 memalign 已过时(参考:手册页),这里仅描述 malloc() 和 posix_memalign() 之间的区别。malloc() 是 8 字节对齐的(例如,对于 RHEL 32 位),但对于 posix_memalign(),对齐是用户可定义的。要了解它的用法,也许一个很好的例子是使用 mprotect() 设置内存属性。要使用 mprotect(),内存指针必须是 PAGE 对齐的。因此,如果您以 pagesize 作为对齐方式调用 posix_memalign(),则返回的指针可以轻松提交给 mprotect() 以设置读写可执行属性。(例如,将数据复制到内存指针后,可以将其设置为只读属性,以防止其被修改)。“malloc()”的返回指针不能在这里使用。
回答by Jaehyuk Lee
When you use posix_memalignin GNU C, you should be careful that second parameter should not only be a power of two, but also be a multiple of sizeof (void*). Note that this requirement is different from the one in the memalign function, which requires only power of two.
当您在GNU C 中使用posix_memalign时,您应该注意第二个参数不仅应该是 2 的幂,而且应该是 sizeof (void*) 的倍数。请注意,此要求与 memalign 函数中的要求不同,后者只需要 2 的幂。
int
__posix_memalign (void **memptr, size_t alignment, size_t size)
{
void *mem;
/* Test whether the SIZE argument is valid. It must be a power of
two multiple of sizeof (void *). */
if (alignment % sizeof (void *) != 0
|| !powerof2 (alignment / sizeof (void *))
|| alignment == 0)
return EINVAL;
void *address = RETURN_ADDRESS (0);
mem = _mid_memalign (alignment, size, address);
if (mem != NULL)
{
*memptr = mem;
return 0;
}
return ENOMEM;
}
weak_alias (__posix_memalign, posix_memalign)
When we look at the first if condition in the posix_memalign implementation, it checks whether alignment is multiple of sizeof(void*).
当我们查看 posix_memalign 实现中的第一个 if 条件时,它检查对齐是否是 sizeof(void*) 的倍数。
回答by lisp-ceo
Facilitates use of THP in the Linux Virtual Memory subsystem: https://youtu.be/fgC6RUlkQE4?t=4930
促进在 Linux 虚拟内存子系统中使用 THP:https: //youtu.be/fgC6RUlkQE4?t=4930
回答by vudangngoc
Deffault malloc return pointer that are multiple of 8, It's mean malloc split memory to chunks have 8 bytes and check free memory at start of each chunk. There are 2 faces of problem.
默认的 malloc 返回指针是 8 的倍数,这意味着 malloc 将内存拆分为具有 8 个字节的块,并在每个块的开头检查空闲内存。问题有2个方面。
Larger chunk will waste more memory, but larger chunk help C find free chunk memory faster. memalign can change how big those chunk is. If you want to save memory, decrease chunk's size to 2 or 4. If you want to make your application faster, increase chunk's size to power of 2.
较大的块会浪费更多的内存,但较大的块有助于 C 更快地找到空闲块内存。memalign 可以改变这些块的大小。如果要节省内存,请将块的大小减小到 2 或 4。如果要使应用程序更快,请将块的大小增加到 2 的幂。

