- memory hierarchy
速度快, 容量小,价格贵,易挥发-》速度慢,容量大,不挥发,便宜
高速缓存:内存的DRAM跟不上CPU的速度
磁盘缓存:
1)读缓存,缓存OS读过的文件
2)写缓存,缓存写操作,达到一定量,一并写入
- memory manager unit MMU
CPU-MMU-Bus-Memory
- address binding
程序执行:
1) 预编译,处理文件头定义的相关文件
2) 编译,高级语言-》汇编语言
3) 汇编,汇编语言-》机器语言
4) 连接, 连接相关的库函数,如printf.o,库函数另存于单独的预编译目标文件中
5) 装入程序
静态链接:
将相关文件二进制直接加入目标文件中,缺点就是占用大量空间
动态链接或共享库:
执行时链入,程序只包含一个关于每个library routine的stub,当stub第一次执行时,routine对应的文件被装入内存,stub被装入的地址代替
- 地址空间:
用于寻址内存的一套地址集合,每个进程都要一个地址空间
- base & limit register
基址:程序的起始物理地址
界:程序的长度
physical= base+limit =》内存总线上
需要加法和比较操作,浪费时间
- 空闲内存的管理
一个分配单元对应一个位图,单元越大位图越小(单位大可能会浪费内存,因为分配是按单元划分),单元越小位图越大,
采用位图的缺点,若要分配K个内存单元,要搜索位图中是否有连续k个0,这个耗时,引入链表,H标识空闲,P标识进程,链表还包括起始,长度和指向下一个节点的指针。
first fit: 浪费内存
next fit: 每次找到合适的就记录当时位置,下次从这个地方开始找
best fit: 搜索整个链表,找到适合的最小空闲区
会很容易的造成很多不可利用的小空闲区
worst fit: 分配最大的空闲区
进程表和空间表可以是独立的,不需要H/P标志,按空闲区大小排序,此时,first fit和best fit一样快,next fit没什么用,进程被删除后,就插入空闲链表
如果不是独立的,进程退出后,P-》H,但是合并空闲区是很费时的
quick fit: 维护一个有特定大小块的,如第一块是4KB,第二块是8KB等
- 没有足够的内存去支持所有运行的进程?
1. swapping
2. virtual memory
每个进程都有自己的地址空间,将地址空间分割成许多chunks,叫做页(一般是512KB到64KB),每个页含有一个连续范围的地址,这些页被映射到物理地址,页在物理内存中对应的单位叫做page frame,并非所有的页都必须在物理内存中,当进程引用某个地址空间时,MMU给出映射,如果这个地址空间在物理内存中没有相应的映射,OS会去获取丢失的部分并重新执行命令
1)假设有64KB的地址空间,32位物理内存
=》16个页8个栈帧,page和栈帧大小相同,4KB
例1: 虚拟地址20500在第5个页面(20480-24575,从0开始算)
此时,从12K-16K的页帧中寻找(起始位置是12288)
所以20500对应的物理地址是:20500-20480+12288=12308
MOV REG, 32780
MMU发现没有映射,产生一个page fault,OS陷入内核,选择了一个只用了一点点的栈帧,将内容写入,重新映射
例:page 8没有被映射,此时释放page 1对应的栈帧,将所有将要进入4096~8191的进程陷入,用page 8->page frame 1代替
16位虚拟地址=4位page number->page frame number->加上12位offsets
present/absent bit是0的话,OS陷入内核,是1,则栈帧被存进output寄存器的high order 3 bits, 然后后面是12位的偏移,组成物理地址,这个寄存器会被放在内存总线上
- 页表
保护位: 可读写、只读等
修改位:如果页面是M,就要写回到磁盘
访问位:未被访问的要比被访问的更适合被淘汰
高速缓存禁止位:映射I/O设备,不需要缓存
- 加速分页过程
虚拟地址到物理地址的映射必须非常快
虚拟地址空间很大,页表也会很大
1)可以在MMU中引进TLB(translation lookaside buffer)
2)多级页表
32位虚拟地址空间
toplevel 第二级
10位pt1 10位pt2 offset
2^10*2^10
entry 0对应代码, entry 1对应数据, entry 1023对应堆栈,其余1021个项absent bit都被设为0
例: PT1=1, PT2=2, OFFSET=4
3) 倒排页表
每个页帧中有一个表项,而不是每个虚拟页面里面有一个表项,表项记录进程,虚拟页面和页帧
例: 当进程n访问页面p时,搜索整个倒排页表是否含有(n,p)
因为每次都需要遍历倒排表,浪费时间,建立一张TLB和散列表,将内存中具有相同散列值的虚拟页面链接在一起,当TLB失效,遍历散列表
- 页面置换
缺页中断,在内存中选择一个页面进行置换,如果换出的页面已经被修改过,就必须把它写回磁盘
1)optimal page replacement
例:一个页面是800万条指令内不会被使用,另一个是650万不会使用,则置换前一个页面
现实中实现不了,可以通过仿真,追踪所有页面的访问情况,在第二次运行时利用第一次运行时收集的信息
2)not recently used page replacement
刚启动时,RM都设置为0,R被定期(典型的时间是20ms)的清0
第0类: 没有被访问,没有被修改
第1类:没有被访问,已被修改
第2类:已被访问,没有被修改
第3类:已被访问,已被修改
NRU淘汰一个没有被访问的已修改要比淘汰一个被频繁使用的干净页面好
3)FIFO
OS维护一个所有当前在内存中的页面的链表,淘汰第一个进入的旧的,将新的放在表尾
4)the second chance page replacement
FIFO可能会将经常使用的页面置换出去,所以将表头是0,则置换,是1,将R为清零,并将页面放于表尾
5)clock page replacement
环形链表,指针指向最老的页面,R如果是0,则淘汰并将新页面插入,指针下移,如果是1,请0,指针下移
6)least recently used page replacement(硬件实现)
两种方案:
每次被引用,计数器加1
例:有4个页框,访问顺序是0123210323
将某行全改为1,将某列都设为0,置换1最少的页面
- 软件模拟LRU
硬件很难实现,使用NFU替代,时钟中断则扫描R,并加到计数器上,问题是可能20s内已被访问多次或者计数器可能始终保存最大,因为某个时刻可能被访问了多次,然后接下来很久没有访问它,但是计数器仍然是最大的=》老化算法(aging)
7) working set
发生缺页中断时,淘汰一个不再工作集中的页面,选定k值,设置长度为k的移位寄存器,没进行一次内存访问就把寄存器左移1位,然后最右端插入访问的页面号,这K个页面就是工作集,当缺页发生,只要读出内容并排序,但是这个方法开销很大。
替代:工作集在过去如10ms内访问过的页面的集合(实际使用CPU的时间-开始执行)
R=0,作为候选,计算生存时间,大于x, 就可以替换,小于x, 选择生存时间最长的
R=1, 如果所有页面都是1,则随机选一个淘汰
8)WSclock
上次使用时间+R
========================================================================