作者:wo缘相聚在空间 | 来源:互联网 | 2023-09-02 12:31
第16章 分段
之前的基址寄存器+界限寄存器会达到内部碎片和外部碎片的问题,内部碎片是由于堆栈可能内存空间使用不充分,中间有空闲内存,但仍分配了对应的物理内存。外部碎片指分配完程序所需的内存空间后,整块内存中间有大大小小的碎片,即为外部碎片。
分段解决了内部碎片问题,为代码、堆和栈分别设置了基址寄存器+界限寄存器。即泛化的基址/界限
那带来了问题,如何确定代码堆栈和寄存器的对应关系呢?
- 显示(将虚拟地址分为分割成段标识+偏移,段标识意指00 01 10 11)
- 隐式(地址由程序计数器产生,地址在代码段,基于栈或基址指针,则在栈,否则在堆)
外部碎片可通过最优匹配、最坏匹配、首次匹配和伙伴算法或定期紧凑内存
分段仍不能很好解决堆大而稀疏的问题,还是会由内存碎片问题
第17章 空闲空间管理
问题:变长的分配请求怎么管理内存?什么策略碎片最小化?相对应的时间空间开销?
假设
- 策略主要关心外部碎片
- 内存分配后不可重定位到其他位置
- 分配程序管理的是连续区域,可以要求其生长
另外分配内存时需要内存大小,但是释放时不需要时由于内存块有个头部,会记录当前分配的内存块大小,当释放时读取即可。
组成部分为:头块(size+magic,hptr指向)+请求分配区域(ptr指向)
基本策略:
最优匹配策略:找到和请求内存大小最接近的内存块,优点是避免浪费,缺点是时间复杂度高,性能损耗大
最差匹配:目的是保留较大的块,而不是像最优匹配一样剩很多小块,策略是找到最大的块进行分割
首次匹配:找到第一个足够大的块即进行分割
下次匹配:在首次匹配的基础上继续向后遍历首次匹配,多维护一个上次分配地址的指针,避免对列表开头频繁分割
分离空闲列表:管理类似相同的分配请求列表,实际应用当内核启动时,为频繁请求的内核对象创建了一些对象缓存,这些对象缓存每个分离了特定大小的空闲列表,因此可以快速响应和释放
伙伴系统:用户合并内存很方便,地址只需要改一位(分配内存时2的次幂,会有内部碎片问题)
第18章 分页
分片:意为将内存分割成固定长度的分片
页表:虚拟内存页定位到对应的页帧上,映射关系存储在内存中
地址空间地址组成: VPN(虚拟页面号) + Offset(偏移量)
第19章 分页:快速地址转换(TLB)
分页:有性能消耗问题,会多一次对页表的内存访问,TLB用来优化该问题
大概流程:从虚拟地址中提取页号,然后检查TLB中是否由该VPN的转换映射,如果有,则有了TLB命中,这意味这TLB有该页的转换映射,接下来就从相关TLB项中取出页帧号(PFN),与原来虚拟地址中的偏移量组合形成期望的物理地址(PA),并访问内存。
如果没有命中,则硬件访问页表寻找转换映射,并将该转换映射更新TLB,TLB更新后会重新执行该整个流程。
总结来看就是TLB相对于页表进行了缓存,访问过一次后即命中后,可加快虚拟地址向物理地址的转换
第20章 分页:较小的表
分页还有另外一个问题:由于页号太多,页表会很大,进而消耗内存过高
策略
1.更大的页:减少了页,但是会带来内部碎片问题
2.混合方法:分段+分页,地址空间分割为 seg + VPN +offset,但对大而稀疏的堆处理的不大好
3.多级页表:页目录(+页次级目录)+页表(思想不局限于特定功能分段,而是将地址空间分成几块,分别对应于目录的映射,分的快速取决于总体页数除以每页能存储的页数)
时间和空间的折中