Linux高性能编程-malloc原理
原创
引言
在Linux系统中,malloc函数是程序员最常用的内存分配函数之一。它用于动态分配内存,令程序可以凭借运行时的需求来调整内存使用。malloc的原理和性能对于领会Linux高性能编程至关重要。
malloc函数简介
malloc是C标准库中的函数,其原型如下:
void *malloc(size_t size);
它接受一个无符号整型参数size,描述需要分配的内存字节数。如果分配顺利,malloc返回一个指向分配内存的指针;如果分配未果,则返回NULL。
malloc的工作原理
malloc的工作原理可以分为以下几个步骤:
- 检查参数size是否有效
- 搜索空闲内存块
- 调整内存块大小以满足请求
- 返回指向分配内存的指针
内存分配策略
Linux中的malloc使用了多种内存分配策略,其中最著名的是ptmalloc(per-thread malloc),也就是POSIX线程版本的malloc。以下是ptmalloc的重点内存分配策略:
- 内存池( arenas ):ptmalloc将内存分成多个内存池,每个线程拥有自己的内存池,以缩减线程间的竞争。
- 大小类( size classes ):内存池中的内存块按照大小被分类,每个大小类包含多个大小相近的内存块。
- 空闲列表( free lists ):每个大小类维护一个空闲列表,列表中的内存块是可用的。
- 内存碎片整理( defragmentation ):当内存池中的空闲内存不足时,ptmalloc会尝试合并相邻的空闲内存块,以缩减内存碎片。
内存分配流程
以下是malloc的详细分配流程:
- 检查请求的内存大小是否在ptmalloc拥护的大小范围内。如果不在这个范围内,malloc将尝试分配一个更大的内存池。
- 搜索当前线程内存池中的空闲列表,找到第一个大小大于或等于请求大小的空闲内存块。
- 如果找到了合适的内存块,检查是否需要调整内存块大小。如果需要调整,将内存块分割成两个部分:一个部分分配给请求者,另一个部分保留在空闲列表中。
- 如果当前线程内存池中没有合适的空闲内存块,检查其他线程的内存池。如果其他线程的内存池中有足够的空闲内存,可以尝试从其他线程的内存池中借用内存块。
- 如果所有线程的内存池都没有足够的空闲内存,ptmalloc将尝试从系统的虚拟内存中分配一个新的内存池。
- 如果无法从虚拟内存中分配新的内存池,malloc将返回NULL,描述内存分配未果。
内存释放
释放内存是malloc的重要补充,它通过free函数实现。free函数的原型如下:
void free(void *ptr);
它接受一个指向已分配内存的指针,ptmalloc将这个内存块标记为空闲,并尝试将其合并到相邻的空闲内存块中,以缩减内存碎片。
内存碎片问题
内存碎片是malloc面临的一个重点问题。内存碎片分为两种:外部碎片和内部碎片。
- 外部碎片:空闲内存块被分割成多个小块,但这些小块的总大小仍然大于请求的内存大小。
- 内部碎片:分配的内存块比请求的内存大小大,出于malloc通常会分配比请求大一点的内存块,以缩减内存碎片。
ptmalloc通过内存池、大小类和空闲列表等机制来缩减内存碎片,减成本时间内存分配的效能。
总结
malloc是Linux系统中非常重要的内存分配函数,它的工作原理和性能对程序的性能有着重要影响。领会malloc的内存分配策略、内存池、大小类和空闲列表等概念,可以帮助程序员编写出更加高效和稳定的程序。