上交 os lec4 内存管理
物理内存
- 以前的物理内存是可插拔的(功耗和性能会有影响),这些内存条一般是那些被CPU访问的内存现在的倾向是集成CPU和内存到一个芯片
早期计算机系统
- 早期计算机系统是单一定制的,不是通用的
多重编程时代
- 讲物理内存分用户使用,隔离性差
IBM 360内存隔离采用Protection Key
- 每一个进程一个key,且每一个2KB的内存块一个key,也就是每一个进程一个内存块但是存在一些缺点
使用物理地址的缺点
虚拟内存抽象
- 虚拟内存是CPU提供的功能,OS只能够使能/配置虚拟内存机制所有的软件使用虚拟地址
虚拟地址
- os不会去翻译虚拟地址,虽然xv6种使用了软件mmu,但一般还是用硬件mmu
虚拟地址翻译过程
过时的分段机制
分页机制
- 分页机制解决了分段机制粒度粗的问题,缓解了内存碎片
页表
- 虚拟页号是index,也就是页表项地址
多级页表
- 多级页表允许页表中出现空洞
AARCH64的4级页表
- 在x86中页表基地址寄存器是CR3
64位虚拟地址翻译
- 在AARCH64中有两个页表基址寄存器
页表使能
- 在CPU上电的时候默认是物理寻址,之后系统软件配置控制寄存器,使能页表,进入虚拟寻址模式。x86中是CR4寄存器第31位置1,使能页表
页表页
- 页表页中存有页表项
AARCCH64页表项
- PXN位可以使得内核不去执行一些用户态代码 当存在bug的时候,内核会去执行用户态代码(比如黑客攻击)00适合内核数据段,01适合应用数据段,10是内核代码段,11是应用代码段
- 第10位适合设置为0时,用来追踪内存访问情况第8/9位适合多核,多设备共享;第4-2位,可以用来表示该内存块是否是走cache访问
arm中的cache lockdown
- cache lockdown寄存器可以用来配置内存块不被驱逐
多级页表tradeoff
- 用时间换空间,TLB解决这个问题TLB在CPU内部
TLB刷新
- 进程切换时,需要刷新TLBx86与AARCH64都可以在系统调用时不用刷新TLB
如何降低TLB刷新的开销
- x86中CR3寄存器的低12位存储PCID身份标签在使用PCID之后,KPTI更加重要x86会使用KPTI来放置Meltdown攻击,那么用户态与内核态页表就是两个了,那么这个时候PCID就尤为关键了,因为系统调用会刷新TLB
TLB和多核
- 在多核的情况下,页表的改变会使得其他的CPU的TLB刷新
TLB结构
- 分级TLB
全局TLB
- nG位置位表示将是所有进程共享的虚/实地址映射
物理内存的超售(Over-commit)和按需分配
- 磁盘的swap页
缺页异常
- 异常号是#PF,错误地址在CR2
按需分配中的权衡
- 页替换策略
Thrashing Problem
- 如果进程过多,那么可能会出现
工作集模型
- 也就是一个进程过去一段时间内会访问的内存页集合,工作集模型假定其之后x时间内也会访问这些页进程工作集要么都不在,要么都在内存中,all-or-nothing
- 固定间隔检查所有页表项计算得到工作集
21世纪看换页
- 物理内存已经很大了
物理内存
- 物理内存的层级
- 物理内存的碎片
- 物理内存管理的评价指标
- 物理内存管理的buddy system伙伴系统中存在很多链表每一个页的大小是4k,那么分配给15k的内存,在22处没有,那么就可以选择一个32K内存分为两个16K内存,其中一个放入22链表,其中一个分配给15K内存的请求
- 伙伴系统可以快速找到伙伴块
建立在伙伴系统的分配器
- os使用buddy system管理页,SLAB分配器家族SLAB分配小内存对象
linux中的SLUB
- os频繁分配的对象大小是相对固定的也就是将2^12大小的页划分为更小的页,进一步划分块,减少内部碎片
- 划分多个资源池,常采用best fit定位资源池
- SLUB存在三个指针current,partial,full,current指向的slab满了,就会去从partial中随便选一个
物理内存安全问题,Rowhammer攻击
- 攻击者频繁访问某一行,会使得其相邻行某些位发生翻转?这会发生提权的错误
- 通过添加guard page防御
性能考虑
- cache coloring解决cache miss
共享内存
- copy-on-write
- memory deduplicationlinux kernel same-page merging会将内存相似的页合并
- 内存去重存在性能问题还有安全问题,比如黑客可以猜密码
内存压缩
- 比如windows10会将一些不太常用的数据压缩(还在内存中),使用时才解压
大页
- 用来标记一个页表中的大小是一个比4k更大的页大页可以减少TLB的使用