系统中的malloc怎么分配内存
malloc 是 C 标准库中的一个函数,用于动态分配内存。
malloc 是通过向操作系统申请内存来实现的。
内存分配的基本原理
malloc函数从堆中分配内存。堆是一个动态内存区域,用于在程序运行时分配和释放内存。- 当程序首次调用
malloc时,它会请求操作系统分配一块较大的内存区域,这个区域被称为内存池(memory pool)。之后的内存分配请求会从这个内存池中划分出一部分内存来满足需求,而不是每次都向操作系统申请内存,这样可以减少系统调用的开销,提高内存分配的效率。
内存分配算法
- 首次适应算法(
First Fit) :在内存池中查找第一个足够大的空闲内存块来满足分配请求。这种方法简单,但可能会导致内存碎片较多。 - 最佳适应算法(
Best Fit) :在内存池中查找最小的且足够大的空闲内存块来满足分配请求。这种方法可以减少内存浪费,但查找过程可能较慢。 - 伙伴系统算法(
Buddy System) :将内存块按大小分成不同的组,当需要分配内存时,从合适的组中划分出一块内存。如果当前组中没有足够的内存块,则向上合并直至找到合适的内存块。这种方法可以有效减少内存碎片,但实现相对复杂。
内存分配的具体过程
- 申请内存池 :当程序启动时,
malloc会向操作系统申请一块较大的内存区域作为内存池。在Linux系统中,通常使用brk或sbrk系统调用,通过调整进程的程序崩溃指针(program break)来增加数据段的大小,从而获得更多的内存空间。在Windows系统中,通常使用VirtualAlloc或HeapAlloc等函数来分配内存。 - 管理内存池 :
malloc使用一定的数据结构来管理内存池中的空闲内存块。常见的数据结构包括链表、位图等。空闲内存块的信息(如大小、起始地址等)被记录下来,以便后续的内存分配和回收操作。 - 分配内存 :当程序调用
malloc请求分配内存时,malloc会在内存池的空闲内存块中查找合适的块来满足请求。根据所采用的内存分配算法,找到合适的空闲内存块后,将其从空闲列表中移除,并返回该块的起始地址给用户。 - 内存回收 :当程序调用
free函数释放内存时,malloc会将释放的内存块重新加入到空闲列表中,以便后续的内存分配请求可以重用这些内存。如果内存池中有多个相邻的空闲内存块,malloc可能会将它们合并为一个更大的空闲块,以减少内存碎片。
GNU C 库中的 malloc 实现
在 GNU C 库(glibc)中,malloc 的实现是一种比较复杂的内存分配器,称为 ptmalloc。主要特点如下:
- 内存池管理 :
ptmalloc将内存池划分为多个arena(区域),每个arena管理一部分内存。在多线程环境下,每个线程可能会有自己的arena,这样可以减少线程之间的竞争,提高内存分配的并发性能。 - 分块管理 :将内存块按照大小分为不同的
bin(桶),每个bin中存放着一定范围大小的空闲内存块。当分配内存时,会根据请求的大小选择合适的bin来查找空闲块;当释放内存时,会将内存块放入合适的bin中。 - 快速分配和释放 :对于小内存块(小于
512字节),ptmalloc使用专门的快速bin(fast bin)来管理,以加快分配和释放的速度。快速bin中的内存块大小相同,分配时直接取出,释放时直接放入,不需要合并和分裂操作。
推荐一下
https://github.com/0voice
