malloc() 内部是如何实现的? [英] How is malloc() implemented internally?

查看:24
本文介绍了malloc() 内部是如何实现的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谁能解释一下 malloc() 在内部是如何工作的?

Can anyone explain how malloc() works internally?

我有时会做strace 程序,我看到很多sbrk 系统调用,做man sbrk 谈到它在malloc() 但仅此而已.

I have sometimes done strace program and I see a lot of sbrk system calls, doing man sbrk talks about it being used in malloc() but not much more.

推荐答案

sbrk系统调用移动数据段的边界".这意味着它移动了程序可以读/写数据的区域的边界(让它增长或缩小,尽管 AFAIK 没有 malloc 确实使用该方法将内存段返回给内核).除此之外,还有 mmap 用于将文件映射到内存,但也用于分配内存(如果您需要分配共享内存,mmap 是您的方法它).

The sbrksystem call moves the "border" of the data segment. This means it moves a border of an area in which a program may read/write data (letting it grow or shrink, although AFAIK no malloc really gives memory segments back to the kernel with that method). Aside from that, there's also mmap which is used to map files into memory but is also used to allocate memory (if you need to allocate shared memory, mmap is how you do it).

所以你有两种从内核获取更多内存的方法:sbrkmmap.关于如何组织从内核获得的内存,有多种策略.

So you have two methods of getting more memory from the kernel: sbrk and mmap. There are various strategies on how to organize the memory that you've got from the kernel.

一种简单的方法是将其划分为专用于特定结构尺寸的区域,通常称为桶".例如,malloc 实现可以为 16、64、256 和 1024 字节结构创建桶.如果您要求 malloc 为您提供给定大小的内存,它会将这个数字四舍五入到下一个存储桶大小,然后为您提供该存储桶中的一个元素.如果您需要更大的区域,malloc 可以使用 mmap 直接与内核分配.如果某个大小的bucket为空malloc可以使用sbrk为新bucket获取更多空间.

One naive way is to partition it into zones, often called "buckets", which are dedicated to certain structure sizes. For example, a malloc implementation could create buckets for 16, 64, 256 and 1024 byte structures. If you ask malloc to give you memory of a given size it rounds that number up to the next bucket size and then gives you an element from that bucket. If you need a bigger area malloc could use mmap to allocate directly with the kernel. If the bucket of a certain size is empty malloc could use sbrk to get more space for a new bucket.

有各种 malloc 设计,并且可能没有一种真正的实现 malloc 的方法,因为您需要在速度、开销和避免碎片/空间效率之间做出折衷.例如,如果一个桶用完元素,则实现可能会从更大的桶中获取一个元素,将其拆分并将其添加到用完元素的桶中.这将非常节省空间,但并非每种设计都可行.如果您只是通过 sbrk/mmap 获得另一个存储桶,那可能会更快,甚至更容易,但空间效率不高.此外,设计当然必须考虑到免费"需要以某种方式再次为 malloc 提供可用空间.你不会只是分发内存而不重用它.

There are various malloc designs and there is propably no one true way of implementing malloc as you need to make a compromise between speed, overhead and avoiding fragmentation/space effectiveness. For example, if a bucket runs out of elements an implementation might get an element from a bigger bucket, split it up and add it to the bucket that ran out of elements. This would be quite space efficient but would not be possible with every design. If you just get another bucket via sbrk/mmap that might be faster and even easier, but not as space efficient. Also, the design must of course take into account that "free" needs to make space available to malloc again somehow. You don't just hand out memory without reusing it.

如果您感兴趣,OpenSER/Kamailio SIP 代理有两个 malloc 实现(它们需要自己的实现,因为它们大量使用共享内存和系统 malloc不支持共享内存).请参阅:https://github.com/OpenSIPS/opensips/tree/master/mem

If you're interested, the OpenSER/Kamailio SIP proxy has two malloc implementations (they need their own because they make heavy use of shared memory and the system malloc doesn't support shared memory). See: https://github.com/OpenSIPS/opensips/tree/master/mem

那你也可以看看 GNU libcmalloc 实现,但是那个很复杂,IIRC.

Then you could also have a look at the GNU libc malloc implementation, but that one is very complicated, IIRC.

这篇关于malloc() 内部是如何实现的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆