当前位置:首页 > 内存 > 正文

请求分页内存分配策略

  • 内存
  • 2024-06-02 05:02:05
  • 3425

一、内存分配(malloc)的过程

[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,)值这个关键值。


二、描述一个包括页面分配与回收、页面置换和存储保护的请求页式存储管理系统请求页面管理系统是一种动态页面管理。
页面分配有相应的“分配算法”。请求表给出了请求的页数--->保存页表并检查是否有足够的空闲页--->否,这次不能分配是,分配并设置页表,完成;请求表中的相关信息,并搜索所请求的空闲页页面,在页表中填写相应的页号。
回收算法很简单,进程执行后,页表和页表都会更新。
替换算法的目标是消除被访问概率最小的页面并将其从内存中移出。常用的算法有:随机淘汰算法、轮换法、先进先出算法、最新未使用页替换算法、理想淘汰算法等。(具体算法和优缺点可以在百度找到,很多资料。)
在存储保护方面,一般有两种方法,一是地址越界保护(由的值决定)。地址改变机制中的控制寄存器——页表的长度和访问的虚拟地址。),另一个是通过页表检查内存信息访问的操作模式以确保保护(在页中添加相应的保护位)桌子)。