当用户应用程序使用C函数库中的内存分配函数malloc()申请内存时,这些动态申请的内存容量或大小均由高层次的C库函数malloc()来进行管理,内核本身并不会插手管理。因为内核已经为每个进程(除了任务0和1,它们与内核代码一起常驻内存中)在CPU的4GB线性地址空间中分配了 64MB的空间,所以只要进程执行时寻址的范围在它的64MB范围内,内核也同样会通过内存缺页管理机制自动为寻址对应的页面分配物理内存页面并进行映射操作。但是内核会为进程使用的代码和数据空间维护一个当前位置值brk,这个值保存在每个进程的数据结构中。它指出了进程代码和数据(包括动态分配的数据空间)在进程地址空间中的末端位置。当malloc()函数为程序分配内存时,它会通过系统调用brk()把程序要求新增的空间长度通知内核,内核代码从而可以根据malloc()所提供的信息来更新brk的值,但并此时并不为新申请的空间映射物理内存页面。只有当程序寻址到某个不存在对应物理页面的地址时,内核才会进行相关物理内存页面的映射操作。
若进程代码寻址的某个数据所在的页面不存在,并且该页面所处位置属于进程堆范围,即不属于其执行文件映像文件对应的内存范围中,那么CPU就会产生一个缺页异常,并在异常处理程序中为指定的页面分配并映射一页物理内存页面。至于用户程序此次申请内存的字节长度数量和在对应物理页面中的具体位置,则均由C库中内存分配函数malloc()负责管理。内核以页面为单位分配和映射物理内存,该函数则具体记录用户程序使用了一页内存的多少字节。剩余的容量将保留给程序再申请内存时使用。
当用户使用内存释放函数free()动态释放已申请的内存块时,C库中的内存管理函数就会把所释放的内存块标记为空闲,以备程序再次申请内存时使用。在这个过程中内核为该进程所分配的这个物理页面并不会被释放掉。只有当进程最终结束时内核才会全面收回已分配和映射到该进程地址空间范围的所有物理内存页面。
有关库函数malloc()和free()的具体代码实现请参见内核库中的lib/malloc.c程序。