操作系统导论-虚拟化

        根据操作系统导论(OSTEP)记录的笔记。

目录

CPU虚拟化

一.进程与进程API

二.进程执行

三.进程调度

内存虚拟化

一.内存API

二.地址空间

三.地址转换机制

四.分段

五.空闲空间管理

六.分页

七.快速地址转换TLB

九.超越物理内存


CPU虚拟化

一.进程与进程API

1.进程

进程是正在运行的程序的抽象。

2.进程状态

        进程可在以下三种状态之间进行转换

                运行:进程运行,执行指令

                就绪:进程准备好运行,但操作系统选择不在此时进行运行

                阻塞:进程等待某个事件的发生

        除这三种状态外,还可能存在其他状态,如创建进程时的初始态(init),未清理的最终态(final)

3.进程API

(1)fork()

        系统调用fork()用于创建新的进程。创建方式是复制一个当前进程,原进程为父进程,新进程为子进程。两个进程返回值是不同的,父进程返回值是子进程的PID,子进程返回0,根据返回值就可以区分父进程与子进程。

(2)wait()

        使用wait()系统调用将会延迟当前进程的执行。

(3)exec()

        exec()系统调用可以让子进程执行与父进程不同的程序。实际上exec()没有创建新的进程,而是直接在当前进程将程序进行替换。

二.进程执行

1.机制:受限直接执行

        为了使程序尽快执行,操作系统使程序在受限制的情况下直接在CPU进行执行。为了限制进程的操作,采用引入用户态(目态)内核态(管态)的方式区分权限。使程序运行在用户态,操作系统运行在内核态。为了满足用户执行特权操作的需求,操作系统提供了系统调用来完成用户进程需要的特权操作。

        执行系统调用需要通过陷阱指令实现,以从用户态切换到内核态。执行陷阱时,处理器将进程的相关信息如寄存器,标志位等保存在内核栈,以在进程重新运行时恢复。

        陷阱发生时如何执行指令,是由内核在启动时设置陷阱表来实现的。

        用户态与内核态转换的三种方式:中断,故障,系统调用

2.进程切换

        协作方式:等待系统调用

        非协作方式:利用时钟中断

        进程切换需要进行上下文切换。

        两种类型的寄存器保存/恢复:

                时钟中断时,寄存器被硬件隐式保存在进程的内核栈

                操作系统决定做进程切换时,将寄存器内容保存到该进程的进程结构内存中

        (:内核在创建进程时会为进程创建相应的堆栈,每个进程有两个栈,用户态运行时使用用户栈,内核态运行时使用内核栈。)

三.进程调度

1.调度指标

        T周转时间=T完成时间-T到达时间

        T响应时间=T首次运行-T到达时间

2.先进先出(FIFO)

3.最短任务优先(SJF)

        假设:任务必须一次完成;任务不同时到达

        在以上假设下到达的短时任务仍然需要等待

4.最短完成时间优先(STCF)

        在SJF的基础上添加了抢占,使平均周转时间大大提高,但响应时间可能很长。

5.轮转(RR)

        在不同时间片执行不同的任务,并不断切换。响应时间短,但周转时间很长。

6.多级反馈队列(MLFQ)

        规则:

        1.优先级A>B,先运行A

        2.优先级A=B,轮转运行AB

        3.工作进入系统时放在最高优先级(最上层队列)

        4.工作用完在一层中的时间配额,就降低优先级

        5.每经过一段时间,将系统中所有工作重新加入最高优先级

7.比例份额调度

        根据希望程序占用时间份额进行分配。如给A=75,B=25,进行0-100随机抽取运行进程。其他的调度机制包括份额转让,通胀等。

        要解决随机性不能产生正确比例的问题,可使用步长调度的方式。如A=100,B=50,C=250,用10000除以这些值得到步长100,200,40。调度时选择行程最小的进程,增加一个步长,实现精确的比例。

内存虚拟化

一.内存API

1.堆内存与栈内存

2.malloc()与free()

        malloc()的调用方式:int*x=(int*)malloc(sizeof(int));   

        malloc返回一个指向void类型的指针,需要使用强制类型转换。

        free(x)释放空间

二.地址空间

1.目标

        透明:OS实现虚拟内存的方式是程序看不见的

        效率

        保护:保证进程、操作系统不会受到另一个进程影响

2.虚拟化内存

        操作系统通过虚拟化内存为进程提供地址空间,进程所有的内存状态都保存在地址空间中。

三.地址转换机制

1.动态重定位(基址加界限)

        地址的转换过程由硬件处理。

        physical address = virtual address + base

        实现该机制的硬件结构位于CPU,这部分也被称为内存管理单元(MMU)。

2.空闲列表

        记录当前没有使用的物理内存范围。

3.操作系统介入

        1.在进程创建时,操作系统需要为进程的地址空间找到内存空间。

        2.进程终止时(正常退出,或因行为不端被强制终止),操作系统必须回收所有内存。

        3.上下文切换时操作系统需要更新基址寄存器和界限寄存器的值。

        4.操作系统需要提供异常处理程序,终止非法操作的进程(如越界访问内存)

4.内部碎片

        由于进程不一定使用很大的堆栈区,预先分配的空间可能处于空闲而造成浪费(内部碎片),因此需要更复杂的机制利用物理内存。

四.分段

1.分段

        三个逻辑不同的段:代码,堆,栈

2.显式段标识

        为了区分特定段,可以将虚拟地址前两位做标识,后面的位表示偏移量。

3.栈的反向偏移

        由于栈反向增长,硬件需要知道段的增长方向。对于栈而言,正确的反向偏移是偏移量-最大偏移量。(如虚拟地址指示偏移3KB,最大偏移4KB,实际地址为基址-1KB。)

4.共享

5.细粒度分段

6.外部碎片

        使用分段的情况下,内存中会出现一些不连续的空闲段,这种问题被称为外部碎片。解决方案是使用紧凑物理内存重新安排已有的段,或采用空闲列表管理算法减小外部碎片。

五.空闲空间管理

1.分割与合并

        分配程序会对空闲列表中的内存空间进行适当的分割与合并。申请空间时分配程序会对符合大小要求的空间进行分割,释放空间时分配程序会将相邻的空闲空间合并。

2.追踪已分配空间的大小

        分配程序通常会使用头块来保存分配大小等信息。

typedef struct header_t {

     int size;

     int magic;

} header_t;

        头块通常位于分配时返回的内存空间之前。

3.空闲列表

4.分配策略

        最优匹配:找到符合条件的空闲块中最小的一块

        最差匹配:找到最大的空闲块

        首次匹配:找到第一个符合条件的空闲块

        下次匹配:从上次查找结束的位置开始查找

        分离空闲列表:如果一个应用经常申请某个大小的内存空间,就用一个独立列表管理这样大小的对象

        伙伴系统:空闲空间被递归的一分为二直至刚好满足请求的大小

六.分页

1.分页

分页的一个例子

        为了记录地址空间的每个虚拟页放在物理内存中的位置,操作系统通常为每个进程保 存一个数据结构,称为页表(page table)。页表是每一个进程的数据结构。

        虚拟页地址转换为物理地址。

        最简单的页表:线性页表(数组)

2.页表项(PTE)的位

        有效位(valid bit):指示特定地址转换是否有效,未使用的中间空间都将被标记为无效如果 进程尝试访问这种内存,就会陷入操作系统。

        保护位(protection bit):表明页是否可以读取、写入或执行。

        存在位(present bit):表示该页是在物理存储器还是在磁盘上。

        参考位(reference bit):追踪页是否被访问

七.快速地址转换TLB

1.TLB

        TLB:地址转换旁路缓冲存储器。每次内存访问,硬件先检查 TLB,看看其中是否有期望的转换映射。

        TLB控制流:

VPN = (VirtualAddress & VPN_MASK) >> SHIFT
(Success, TlbEntry) = TLB_Lookup(VPN)
if (Success == True) // TLB Hit
    if (CanAccess(TlbEntry.ProtectBits) == True)
        Offset = VirtualAddress & OFFSET_MASK
        PhysAddr = (TlbEntry.PFN << SHIFT) | Offset
        AccessMemory(PhysAddr)
    else
        RaiseException(PROTECTION_FAULT)
else // TLB Miss
    PTEAddr = PTBR + (VPN * sizeof(PTE))
    PTE = AccessMemory(PTEAddr)
    if (PTE.Valid == False)
        RaiseException(SEGMENTATION_FAULT)
    else if (CanAccess(PTE.ProtectBits) == False)
        RaiseException(PROTECTION_FAULT)
    else
        TLB_Insert(VPN, PTE.PFN, PTE.ProtectBits)
        RetryInstruction()

2.TLB未命中的处理:

        对于有复杂指令集(CISC)的计算机,硬件处理TLB未命中的情况。在这些计算机中,硬件知道页表的位置与格式,当TLB未命中时,硬件遍历页表,找出正确的页表项并更新TLB。

        精简指令集(RISC)计算机有软件管理TLB,TLB未命中时,硬件抛出异常,OS转入内核模式跳转至陷阱处理程序,处理TLB未命中的情况。(1)从陷阱返回时,硬件重试导致陷阱的指令,这与系统调用不同。2Os需要避免无限递归未命中,可以将未命中处理程序放入物理内存,或在TLB中记录永久有效的地址转换。

3.TLB的内容:

        VPN | PFN | 其他位(有效位、保护位…)        TLB的有效位与页表的有效位不同

4.上下文切换对TLB的处理:

        (1)上下文切换时清楚TLB的内容。上下文切换时,OS会更新页表基址寄存器,硬件可以在此时清空TLB,将全部有效位设为0。

        (2)添加地址空间标识符(ASID

5.TLB替换策略:最少使用的(RLU)/随机替换

6.TLB存在的问题:

(1)短时访问页数超过TLB页数,会导致大量未命中,称为超出TLB覆盖范围

(2)流水线瓶颈

八.页表(实现更小的页表)

1.分页与分段混合

        为每个逻辑分段提供一个页表,每个分段的基址寄存器指向页表的物理地址,界限寄存器保存了段中最大有效页的值。

2.多级页表

        当TLB未命中时,需要从内存中加载两次才能得到正确的地址,这是使用多级页表的成本。

九.超越物理内存

1.交换空间

在硬盘开辟空间,将物理页移入移出,实现比物理内存空间更大的地址空间。

        为了保证少量空闲空间,大多数操作系统会设置高水位线(HW),低水位线(LW)。操作系统发现可用页少于LW时,会唤醒线程释放内存,直至有HW个页可用,这个线程称为页守护进程交换守护进程

2.存在位

        通过页表项中的存在位,判断页是否在物理内存当中。

3.页错误

        访问不在物理内存中的页,被称为页错误。操作系统处理页错误,用页表项中的位来表示存储硬盘地址,并将请求硬盘,将页读入内存中,当硬盘I/O完成后,更新页表项中内存位置的内容,再重新访问TLB。

4.缓存管理

        内存包含所有页的子集,因此可看作是虚拟内存页的缓存。选择替换策略时,目标是让缓存未命中最少。

        已知命中未命中次数,可计算程序平均内存访问时间(AMAT)。TM、TD为访问内存、磁盘的成本。AMAT = (PHit·TM) + (PMiss·TD)        (Pmiss+Phit=1.0)

5.最优替换策略

          最优替换策略:总是替换出最远的将来被访问的页。       

        补充:缓存未命中的类型

        有时未命中会被分为3类:强制性、容量和冲突未命中,有时称为 3C 。发生强制性      (compulsory miss)未命中(或冷启动未命中,cold-start miss [EF78])是因为缓存开始是空的,而这是对项目的第一次引用。由于缓存的空间不足而需要替换项目进入缓存,为容量未命中(capacity miss)。第三种类型的未命中(冲突未命中,conflict miss) 出现在硬件中。

6.替换策略

(1)FIFO

(2)随机

(3)LFU策略

补充:局部性类型

        程序倾向于表现出两种类型的局部。第一种是空间局部性(spatial locality),指出如果页 P 被访问,可能围绕它的页(比如 P−1 或 P + 1)也会被访问。第二种是时间局部性(temporal locality),指出近期访问过的页面很可能在不久的将来再次访问。

(4)近似LFU

硬件增加一个使用位(或引用位),每当页被读写时置为1,借这一位实现近似LFU。

        时钟算法:所有的页放入一个循环列表,时钟指针开始指向任意一个页,当必须进行替换时,从列表中找到第一个使用位为0的页进行替换,遇到使用位为1的页则将该位置0。

        考虑脏页:被修改过的页称为脏页,将这样的页写入硬盘需要付出成本,因此系统倾向于替换干净页,为此硬件需要添加修改位(脏位)。

(5)其他策略:预取;聚集写入

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值