Linux 使用 mmap 和 munmap 实现您自己的 malloc/free
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8475609/
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
Implementing your own malloc/free with mmap and munmap
提问by MetallicPriest
I have implemented by own mallocand freeusing mmap. Now since unlike free, munmapalso takes length as parameter, therefore I put length as an additional information in the mapped memory.
我已经通过自己的malloc和free使用mmap 实现了。现在与free不同,munmap也将长度作为参数,因此我将长度作为附加信息放在映射内存中。
The code for my mallocand freeis shown below. I want to ask, if this code is good or am I still missing anything or doing something in a wrong way.
我的malloc和free的代码如下所示。我想问一下,如果这段代码很好,还是我仍然遗漏了什么或以错误的方式做某事。
void * malloc ( size_t size )
{
int *plen;
int len = size + sizeof( size ); // Add sizeof( size ) for holding length.
plen = mmap( 0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 );
*plen = len; // First 4 bytes contain length.
return (void*)(&plen[1]); // Memory that is after length variable.
}
void free ( void * ptr )
{
int *plen = (int*)ptr;
int len;
plen--; // Reach top of memory
len = *plen; // Read length
munmap( (void*)plen, len );
}
回答by unwind
Some observations:
一些观察:
- You assume that
int
andsize_t
have the same size. If you want to store asize_t
value at the head of the allocation, then why don't you just do that? Why introduceint
? - This will very likely be quite inefficient, both in terms of memory usage and speed. There is significant overhead to
mmap()
, and typically allocations cannot be smaller than a "page". Most real allocators try to avoid calling OS-level functionality on everymalloc()
, in various ways. - If
mmap()
fails, it will returnMAP_FAILED
, and so shouldmalloc()
. Thus, you need to test for that beforede-referencing the pointer returned bymmap()
. - Calling
free(NULL)
should be a valid thing to do; with your implementation it will very likely cause a crash since you don'tNULL
-check the argument before assuming it's valid.
- 您假设
int
和size_t
具有相同的大小。如果您想size_t
在分配的开头存储一个值,那么为什么不这样做呢?为什么要介绍int
? - 就内存使用和速度而言,这很可能非常低效。有显着的开销
mmap()
,并且通常分配不能小于“页面”。大多数真正的分配器都试图以malloc()
各种方式避免在 each 上调用操作系统级功能。 - 如果
mmap()
失败,它将返回MAP_FAILED
,因此也应该返回malloc()
。因此,您需要在取消引用由 返回的指针之前对此进行测试mmap()
。 - 打电话
free(NULL)
应该是一件有效的事情;对于您的实现,它很可能会导致崩溃,因为您NULL
在假设它有效之前没有检查参数。
回答by user964970
You should, at least.
你应该,至少。
- Check if
mmap
fails - store a
size_t
for the size, not anint
. They might be different. - return suitable aligned memory, the memory here seems to be 4 byte aligned (as you add an
int
, presumably 4 bytes, to the page aligned data from mmap. This means storing values that need larger alignment in the returned memory, e.g. a double incurs a performance penalty, or outright crashes on some architectures. - Handle
NULL
being passed to free (it's supposed to be a no-op)
- 检查是否
mmap
失败 - 存储一个
size_t
大小,而不是一个int
。他们可能不同。 - 返回合适的对齐内存,这里的内存似乎是 4 字节对齐的(当您向
int
mmap 中的页面对齐数据添加一个,大概是 4 个字节时。这意味着在返回的内存中存储需要更大对齐的值,例如 double 会导致性能损失,或在某些架构上彻底崩溃。 - 句柄
NULL
被传递给免费(它应该是一个空操作)
For a malloc implementation, i'd also expect it to at least have rudimentary debugging support, e.g. try to detect double frees, try to detect free'ing invalid pointers, list memory not free'd etc.
对于 malloc 实现,我还希望它至少具有基本的调试支持,例如尝试检测双重释放、尝试检测释放无效指针、列出未释放的内存等。
Keep in mind your malloc implementation here can be extremely wasteful. If you malloc 10 bytes , you'll end up allocating 1 page (4096 bytes), that all have to be mapped to physical memory, with the remaining 4082 bytes being unused.
请记住,这里的 malloc 实现可能非常浪费。如果您 malloc 10 bytes ,您最终将分配 1 页(4096 字节),所有这些都必须映射到物理内存,其余 4082 字节未使用。
回答by Basile Starynkevitch
Read also c malloc on wikipediaand study carefully some real malloc implementations like Doug Lea's malloc. There is a lot of litterature on the subject, e.g. by Wolfram Glogerand many many others.
另请阅读维基百科上的 c malloc并仔细研究一些真正的 malloc 实现,如Doug Lea 的 malloc。有很多关于这个主题的文献,例如Wolfram Gloger和许多其他人的著作。
@MetallicPriest: you really should explain much much more what you are doing (I am not very optimistic for your work, but you'll probably learn a big lot!)
@MetallicPriest:你真的应该解释更多你在做什么(我对你的工作不是很乐观,但你可能会学到很多东西!)
回答by puikos
You shouldn't call mmap each time you call your custom malloc. As stated before there is a huge overhead doing this.
每次调用自定义 malloc 时都不应该调用 mmap。如前所述,这样做会产生巨大的开销。
You should create a large sized shared memory (4K for example) and your malloc function will only have to return pointers in the range of the memory you alocated.
您应该创建一个大尺寸的共享内存(例如 4K),并且您的 malloc 函数将只需要返回您分配的内存范围内的指针。
Then if you get short on memory you create an other 4k of shared memory.
然后,如果您的内存不足,您可以创建另一个 4k 的共享内存。
You'll just have to count how much space you use and keep track of your references and that way freeing memory is much easier.
你只需要计算你使用了多少空间并跟踪你的引用,这样释放内存就容易多了。
回答by remus
And you also should use -1
instead of 0
as the fd argument of mmap.
你也应该使用-1
而不是0
作为 mmap 的 fd 参数。
mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
MAP_ANONYMOUS
The mapping is not backed by any file; its contents are initialized to zero. The fd and offset arguments are ignored; however, some implementations require fd to be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable applications should ensure this. The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is supported on Linux only since kernel 2.4.
MAP_ANONYMOUS
映射不受任何文件的支持;它的内容被初始化为零。fd 和 offset 参数被忽略;但是,如果指定了 MAP_ANONYMOUS(或 MAP_ANON),某些实现要求 fd 为 -1,并且便携式应用程序应确保这一点。MAP_ANONYMOUS 与 MAP_SHARED 结合使用仅在 Linux 内核 2.4 后才支持。