[TOC]
内存分配函数(例如malloc和mmap)仅创建进程的虚拟地址空间,并不分配实际的物理内存。当进程访问没有映射关系的虚拟内存时,会自动触发缺页错误。
在请求分页的系统中,可以通过查询页表的当前状态位来检查当前页是否在内存中,如果不在内存中,可以读取缺失页的外存地址在内存页表中。例如,映射文件mmap.
使用ps-omajflt、minflt-Cprogram命令查看。
majflt表示majorfault(需要读盘),中文名称为majorfault,minflt表示minorfault(无需读盘),中文名称为minorfault。
这两个值代表自进程启动以来发生的页面错误数。
当进程发生页面错误时,该进程会陷入内核态,并执行以下操作:
如果第3步需要读磁盘,那么这个页面中断interruptIamajflt,如果没有则minflt。
从操作系统的角度来看,两种方式处理内存分配,都是通过两个系统调用完成的:brk和mmap(不考虑共享内存)。
这两种方法都分配虚拟内存,不分配物理内存。当分配的虚拟地址空间第一次被访问(读/写)时,就会发生页面错误。操作系统负责分配物理内存,然后建立虚拟内存和物理内存的映射关系。
标准C库中,提供了malloc/free函数来分配和释放内存,这两个函数底层是通过brk、mmap、munmap等系统调用来实现的。
如果malloc小于128k内存,则使用brk分配内存,并将_edata推送到更高的地址。
对于malloc内存大于128k,使用mmap分配内存,并在之间查找堆和堆上分配一块空闲内存(等于空闲内存并初始化为0)
MMap内存释放在前面的brk内存释放部分介绍过
既然堆brk中的内存不能直接释放,为什么不使用mmap来分配,munmap直接释放呢?
其实,进程使用sbrk/mmap/munmap接口来请求和释放地址空间来自OS的都是系统调用,而且是比较常用的系统调用。另外,mmap申请的内存是munmap后,重新申请会产生更多的分页符。例如,使用mmap分配1M空间,第一次调用会产生大量缺页(1M/4K次,再次使用munmap分配1M空间,会产生大量缺页)。再一次。页面中断是内核行为,会导致内核模式下CPU使用率过高。另外,如果使用mmap分配小内存,会导致地址空间碎片较多,内核管理负担较大。
同时,堆是连续的空间,堆中的碎片不会返回给操作系统,如果碎片可以重用,再次访问内存可能不需要任何系统调用和页面中断。,这将减少CPU使用率。因此,glibc的malloc实现充分考虑了brk和mmap行为上的差异和优缺点默认情况下,在使用mmap获取地址空间之前会分配一大块内存(128k)也可以修改mallopt(M_MMAP_THRESHOLD,
上一篇:电视1.5+8g内存够用吗
下一篇:内存的分段和分页