ucore lab3 操作系统实验

LAB3实验报告

知识准备

(主要依据理论课知识以及学堂在线上清华大学教学视频)

1.虚拟存储的相关概念:

​ 虚拟存储是一种内存管理技术指的是在非连续内存分配的基础上,将一部分内容放到外存里的做法,从而可以使在内存中保留更多进程并且可以允许进程比主存的全部空间还大。

虚拟存储的需求背景:

程序规模的增长速度远大于存储器容量发展速度,导致系统时常出现内存不够用的情况。

我们想拥有有容量更大、速度更快、价格更便宜的非易失性存储器,但根据储存器的层次结构我们知道,容量大的存储器访问速度就慢,访问速度快的存储器价格就比较昂贵。因此需要用一种技术使这些存储器的搭配处于合理状态,使得既满足容量与速度需求,又尽可能低成本。

交换与覆盖技术

覆盖技术是指依据程序的逻辑结构,将程序划分为若干个功能相对独立的模块,将不会同时执行的模块可以共享同一块内存,按时间先后运行。可以将常用功能的代码和数据常驻内存,不常用功能的代码数据放在其他程序模块中,只在需要使用时将其装入内存。交换技术可以实现允许进程内存比主存全部空间还大的情况。但覆盖技术增大了程序编程的复杂性,程序的设计开销大大增加,本质上是一种以时间换空间的策略。

交换技术可以增加正在运行或者需要运行的程序的内存,实现方法为将暂时不运行的程序放到外存。通常使用于内存空间不够或者很可能不够的情况,交换区大小的设置应当满足可以存访所有用户进程的所有内存映像的拷贝;当然,通过采用动态地址映射的方法,当程序再次换入时不需要一定放置在原地址。

覆盖发生在运行程序的内部模块间,只能发生于没有调用关系的模块间。而交换是以进程为单位,发生在内存的进程之间。

局部性原理

程序在执行过程中的一个较短时期,所执行的指令地址和指令的操作数地址,分别局限于一定区域。

时间局部性:一条指令的一次执行和下次执行,一个数据的一次访问和下次访问都集中在一个较短时期内。

空间局部性:当前指令和临近的几条指令,当前访问的数据和临近的几个数据都集中在一个较小范围内。

分支局部性:一条跳转指令的两次执行,很可能跳到相同的内存位置。

因此根据程序局部性原理,我们认为程序所执行的指令以及访问的数据都有很好的集中特征,因此如果知道这些局部区域的位置,将其放入内存,将别的不常用的放在外存中,这样可以使得系统不会因为频繁的内存与外存间的换入换出导致性能大幅度下降。

虚拟存储的实现

思路:将不常用的部分内存块暂存到外存中

原理:装载程序时,只将当前指令执行所需要的部分页面或段装入内存;指令执行中发生缺页或者缺段时,操作系统将相应的页或段调入内存;操作系统将内存中暂时不用的页或段保存到外存。

实现方式:虚拟页式管理和虚拟段式管理

虚拟页式存储

将每次交换的单位设置为页即可。实现方式为在页式存储管理的基础上,增加请求调页和页面置换算法。

思路:当程序要装载到内存运行时,只装入部分页面,就启动程序运行。程序在运行中发生代码或数据不在内存时,则向系统发出缺页异常请求。操作系统处理缺页异常时,将外存中相应的页面调入内存使进程可以继续运行。

虚拟页式存储中的页表项结构:在这里插入图片描述
逻辑地址通过页表转换到物理地址对应的帧,加上偏移量即可找到正确的物理地址空间。

当页表中发现要访问的页不在内存时,引发缺页异常,操作系统将调度一个磁盘操作将要访问的外存中的页调度到内存中的帧,并刷新页表,然后重新执行该指令。

具体页表项的组成(增添了一些标记位):
在这里插入图片描述

  • 驻留位:表示该页是否在内存(1表示在该页内存,该页有效可以访问;0表示该页在外存,访问该页会引发缺页异常)
  • 修改位:表示在内存中的该页是否被修改过(用于回收该物理页时,判断是否需要将其内容写回外存)
  • 访问位:表示该页面是否被访问过(主要用于页面置换算法)
  • 保护位: 表示该页的允许访问方式(可读?可写?可执行?等)
缺页异常处理

发生缺页异常,操作系统将调度一个磁盘操作将要访问的外存中的页调度到内存中的帧,并刷新页表,然后重新执行该指令。 如下:
在这里插入图片描述
如果内存中有空闲的物理页面,则直接分配一个空闲物理帧即可。否则需要根据页面置换算法选择被替换的物理页帧以及对应的逻辑页,根据逻辑页的修改位判断该页是否被修改过,如果修改过需要将其写回外存。之后将这个逻辑页的驻留位置为0。将要访问的页装入给其分配的物理页帧,修改其驻留位为1并修改相应的物理页帧号。最后重新执行该指令。

虚拟页式存储管理的性能:

EAT(有效访问时间)=访存时间*(1-p)+缺页异常处理时间 *缺页率p

2.页面置换算法

当出现缺页异常时,需要调入新页面而内存已满时,置换算法来选择被置换的物理页面。置换算法的设计目标是尽可能减少页面的换入换出次数,把未来不再访问或短期不访问的页面调出。页面置换算法通常分为局部页面置换算法和全局页面置换算法,局部置换算法的置换页面的选择范围仅限于当前进程占用的物理页面内,全局置换算法的置换页面的选择范围是所有可换出的物理页面。

最优页面置换算法(OPT)

当需要调入一页必须淘汰一个旧页时,置换的页是以后不会访问或最长时间不会使用的页。该算法是最优的算法,缺页最少,但是是理想情况下的算法,由于不能预测之后要访问的页以及每个页面距离下次访问的时间,故操作系统是不能实现的,但通常作为一个标准衡量别的算法的性能。下面是一个例子(理解下面这个过程即可):
在这里插入图片描述

先进先出算法(FIFO)

当需要调入一页必须淘汰一个旧页时,总是淘汰最先调入内存的那一页,或者说在主存中驻留时间最长的那一页。该算法实现较为简单,只需要维护一个位于所有内存中的逻辑页面链表,链表元素按照驻留时间排序,链首最长,如果出现缺页时将链首页面进行置换,新页面加到链尾即可。但是该算法性能较差,可能会将经常调用的页面调出,可能导致Belady异常(页错误率可能会随着所分配的帧数的增加而增加)。下面是一个例子(理解该例子即可):在这里插入图片描述

最近最少使用算法(LRU)

当需要调入一页必须淘汰一个旧页时,总是淘汰最近一段时间内最长没有被引用的页面进行置换。根据程序局部性原理,那些刚被使用过的页面,可能马上还要被使用,而较长时间里没有使用的页面,可能不会马上使用到。实现:当发生缺页时,计算内存中每个逻辑页面的上一次访问时间,选择上一次使用到当前时间最长的页面。具体实现时候可以维护一个按最近一次访问时间排序的页面链表,链表首节点是最近刚使用过的页面,尾节点是最久未使用的页面,访问内存时,找到相应的页面并把它移到链首,缺页时置换链表尾节点的页面。

可以认为这是最优置换算法的一种近似,算法性能较好,但实现非常复杂。下面是一个例子:
在这里插入图片描述

时钟置换算法

当需要调入一页必须淘汰一个旧页时,淘汰最近的时间段没有访问的页面。可以认为是FIFO与LRU的一种折中方案,考虑之前的访问情况,但不是考虑之前所有的访问情况。通过对过去一段时间页面的访问情况进行统计即可,为了实现该算法,通常在页表项中增加访问位,当装入内存时,访问位初始化为0,访问页面时访问位置为1;且各页面组织成环形链表,指针总是指向最先调入的页。访问页面时,在页表项记录页面访问情况;缺页时,从指针处开始顺序查找未被访问的页面进行置换,访问位为0的话置换该页,如果为1向下继续找。例子:
在这里插入图片描述

最不常用算法

当需要调入一页必须淘汰一个旧页时,淘汰最近访问次数最少的页。实现:每个页面设置一个页面计数,访问页面时访问次数加1,缺页时只需要置换计数最小的页面。例子:在这里插入图片描述

实验过程

进行实验之前,我们查看一些lab3新增的一些重要的数据结构和函数:

查看vmm.h可知有两个重要的数据结构vma_struct和mm_struct,描述了ucore模拟应用程序运行所需的合法内存空间 。当访问内存产生page fault异常时,可获得访问的内存的方式(读或写)以及具体的虚拟内存地址,从而ucore就可以查询此地址,看是否属于vma_struct数据结构中描述的合法地址范围中,如果在,则可根据具体情况进行请求调页/页换入换出处理;如果不在,则报错。代码介绍:

vma_struct是用来描述应用程序对虚拟内存“需求”的数据结构:

//虚拟内存空间
struct vma_struct
 {
   
    //虚拟内存空间属于的进程
    struct mm_struct *vm_mm; 
    //描述了一个连续地址的虚拟内存空间的起始位置和结束位置,这两个值都应该是PGSIZE 对齐的,
    //而且描述的是一个合理的地址空间范围(即严格确保 vm_start < vm_end的关系
    uintptr_t vm_start;           
    uintptr_t vm_end;        
    //虚拟空间的属性(读/写/可执行)
    uint32_t vm_flags;      
    //双向链表,从小到大将虚拟内存空间连起来
    list_entry_t list_link; 
};
//需要说明的是vm_flags表示虚拟内存空间属性,共三种:
#define VM_READ 0x00000001 //只读
#define VM_WRITE 0x00000002 //可读写
#define VM_EXEC 0x00000004 //可执行

mm_struct则更像是一个包含所有虚拟内存空间的共同属性的结构体:

//描述一个进程的虚拟地址空间,每个进程的pcb有一个指针指向该结构体
struct mm_struct {
   
    //双向链表头,链接了所有属于同一页目录表的虚拟内存空间
    list_entry_t mmap_list;        // linear list link which sorted by start addr of vma
    //指向当前正在使用的虚拟内存空间,
    struct vma_struct *mmap_cache; // current accessed vma, used for speed purpose
    //mm_struct数据结构所维护的页表
    pde_t *pgdir;                  // the PDT of these vma
    //记录mmap_list 里面链接的 vma_struct的个数
    int map_count;                 // the count of these vma
    //指向用来链接记录页访问情况的链表头(用于置换算法)
    void *sm_priv;                   // the private data for swap manager
};
//补充:
//mmap_cache变量可以使程序更好地利用操作系统执行的“局部性”原理,现阶段使用地虚拟内存空间接下来很可能还用到,所以如果直接用到地话直接调用mmap_cache将很好地提高效率。
//通过访问pgdir可以查找某虚拟地址对应的页表项是否存在以及页表项的属性

与vma_struct和mm_struct相关的函数:(仅对函数作用做介绍,不介绍具体实现)

//创一个mm_struct并初始化,(创建时调用了kmalloc,故删除前需要释放)
struct mm_struct *mm_create(void) 

// vma的创建并初始化,根据参数vm_start、vm_end、vm_flags完成初始化
struct vma_struct *vma_create(uintptr_t vm_start
  • 8
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值