最近在阅读linux源码,版本为早期的0.11。读到内存动态分配的部分时,想起以前面试的时候遇到的一个问题:free释放内存的时机是什么?是调用时立即释放还是在别的某个时机释放?对于这个问题,之前查资料并未找到比较详细的解释。阅读这一部分内容后终于对这一问题有了答案,因此对这一问题进行总结。
c语言函数库提供了malloc函数来进行内存分配,分配的内存在进程管理的堆上,这一部分内存由程序员自己管理,内核本身不会插手。但是内核会为进程使用的代码和数据空间维护一个当前位置值brk,这个值会保存在每个进程的数据结构中,它指出了进程代码和数据(包括动态分配的数据空间)在进程地址空间中的末端位置,当使用malloc函数分配内存时,会通过系统调用brk()将需要新增的内存空间长度通知内核,内核代码根据malloc所提供的信息来更新brk的值,但此时并不为新申请的空间映射物理内存页面。只有当程序寻址到某个不存在的物理页面时,内核才进行相关的物理内存页面的映射操作。
当进程寻址的某个数据所在的页面不存在,并且该页面所处的位置属于进程的堆范围,cpu会产生一个缺页异常,通过异常处理程序为指定的页面分配并映射一页的物理内存。对于用户程序申请的内存的字节长度以及在物理页面中的具体位置由malloc函数管理。该函数会具体记录用户程序使用了一页内存中的字节数,剩下的容量保留给程序再次申请内存时使用。
当用户使用内存释放函数free()动态释放已申请的内存块时,c库中的内存管理函数会把释放的内存块标记为空闲,备与程序再次申请的时候使用。在这个过程中内核为进程分配的物理页面并不会被释放。只有当整个进程结束时内核才会全面回收已经分配到该进程空间范围的所有物理内存页面。
因此可以认为当我们调用free函数释放某一块区域的内存时,free只是将这一块内存标记为空闲,实际上这一块物理内存还是属于该进程的,只有当整个进程结束后,才会全面回收这一块物理内存页面。