free() 是否取消映射进程的内存?

free() 是否取消映射进程的内存?

我正在 Linux 2.6.16 内核上运行 C 程序。我不认为我的程序存在内存泄漏,但是程序的内存消耗在某些操作后保持稳定并且不会减少。我使用“ps v”命令来监视程序的 RSS 值。

valgrind Massif 工具显示在我的进程中大部分堆是通过 mmap 分配的。但根据代码,这些分配应该在操作完成后被释放。是否因为释放的内存仍然被映射和/或仍然对进程的 RSS 值有贡献?

任何见解将不胜感激!

以下是 valgrind 地块报告的片段。注意我已经打开了 Massif 工具的 --pages-as-heap 选项来测量程序使用的所有内存。

--------------------------------------------------------------------------------
  n        time(i)         total(B)   useful-heap(B) extra-heap(B)    stacks(B)
--------------------------------------------------------------------------------
 85 701,483,989,262      173,576,192      173,576,192             0            0
 86 704,352,949,469      173,367,296      173,367,296             0            0
 87 707,582,275,643      173,367,296      173,367,296             0            0
 88 710,536,145,814      173,367,296      173,367,296             0            0
100.00% (173,367,296B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc.
->53.40% (92,581,888B) 0x649248B: mmap (in /lib64/tls/libc.so.6)
| ->41.13% (71,303,168B) 0x6446D85: _int_malloc (in /lib64/tls/libc.so.6)
| | ->39.31% (68,157,440B) 0x6448D62: calloc (in /lib64/tls/libc.so.6)
......[my own functions are omitted]
->35.28% (61,157,376B) 0x400F51B: mmap (in /lib64/ld-2.3.3.so)
| ->28.81% (49,954,816B) 0x4004CE8: _dl_map_object_from_fd (in /lib64/ld-2.3.3.so)
| | ->28.81% (49,954,816B) 0x400636B: _dl_map_object (in /lib64/ld-2.3.3.so)
| |   ->18.89% (32,755,712B) 0x400AB42: openaux (in /lib64/ld-2.3.3.so)
| |   | ->18.89% (32,755,712B) 0x400AF7C: _dl_catch_error (in /lib64/ld-2.3.3.so)
| |   |   ->18.89% (32,755,712B) 0x4009FCF: _dl_map_object_deps (in /lib64/ld-2.3.3.so)
| |   |     ->18.89% (32,755,712B) 0x40021FD: dl_main (in /lib64/ld-2.3.3.so)
| |   |       ->18.89% (32,755,712B) 0x400E7F6: _dl_sysdep_start (in /lib64/ld-2.3.3.so)
| |   |         ->18.89% (32,755,712B) 0x4001477: _dl_start (in /lib64/ld-2.3.3.so)
| |   |           ->18.89% (32,755,712B) 0x4000CF6: ??? (in /lib64/ld-2.3.3.so)
| |   |             ->18.89% (32,755,712B) 0x0: ???
| |   |               ->18.89% (32,755,712B) 0x7FF0003D5: ???
| |   |                 ->18.89% (32,755,712B) 0x7FF0003E4: ???
| |   |
......

答案1

C 库函数free()可以(但不是必须)将内存返回给内核。

一些实现malloc()通过系统调用移动“堆”和其他未使用的地址空间(“系统中断”)之间的边界sbrk(),然后分配这些大分配中的较小部分。如果不取消分配每个较小的部分,free()就无法真正将内存返回给操作系统。

同样的原因也适用于malloc()不使用sbrk(2),但可能使用mmap("/dev/zero")或其他东西的实现。我找不到参考资料,但我似乎记得某个 BSD 使用mmap()这种方式来获取内存页。然而,free()除非程序释放每个子分配,否则无法将页面返回到操作系统。

有些malloc()实现确实将内存返回给系统:ChorusOS(?)显然是的。目前尚不清楚它是否移动了系统中断或munmap()'ed页面。

这是一篇关于内存分配器的论文通过“积极地将空闲页面交给虚拟内存管理器”来提高性能。 幻灯片放映以供演讲关于分配器。

相关内容