OS-lab2
OS-lab2
启动之后,我们的操作系统要能运行,需要一个载体,就是内存。内存的访问不是直接的,而是通过MMU完成。在完成MMU之前,我们先看看一些需要用到的宏定义和函数。
include
pmap.h
定义了内存控制块
Page
结构体,用于记录页面的分配和使用情况。其中pp_link
有两个成员,*le_next
用于指向下一个元素,le_prev
用于指向前一个元素的**le_next
的地址。pp_ref
用于记录页面被引用的次数。
page2pa
函数通过给定的Page
控制块计算对应的页面的物理地址。
page2ppn
函数通过给定的Page
控制块计算这个页面控制块在整个页面控制块数组中的下标。
pa2page
函数通过给定的物理地址计算对应的页面控制块。
page2kva
函数通过给定的Page
控制块计算计算这个页面对应的内核虚地址。
va2pa
函数通过给定的页目录和虚拟地址计算对应的物理地址。此外还声明了pmap.c中的一些函数。
queue.h
通过宏定义定义了关于链表的一些操作,如初始化、插入删除等。
mmu.h
定义了一系列变量如页面大小
BY2PG
、标志位PTE_V
等。PDX(va)
用于获得虚拟地址的高10位,PTX(va)
类似。PADDR(kva)
用于将内核虚拟地址转化为物理地址,KADDR
正好相反。PTE_ADDR
用于获得页表项存储的物理地址。
现在,我们一步一步实现MMU。
mm
pmap.c
这个文件集合了管理内存的大部分函数。其中
*pages
是页面控制块数组,freemem
是空闲内存的地址。mips_detect_memory
函数手动给basemem
、maxpa
、npage
等全局变量进行了赋值。
*alloc
函数手动分配n字节的空闲内存。具体思路即修改freemem
的值,然后将alooced_mem
清零后返回这个地址。
*boot_pgdir_walk
函数用于获取对应虚拟地址对应的二级页表项。具体流程是通过页目录找到页目录项地址;将页目录项的值转为虚拟地址;检查是否存在,若不存在且create
为1,就分配一页,并给对应的页表项赋上标志位;然后再求得对应二级页表项的虚拟地址并返回。
boot_map_segment
函数用于将size
大小的虚拟地址区间映射到size
大小的物理地址区间。首先将size
按BY2PG
取整;然后以页为单位,利用*boot_pgdir_walk
获得每一页的页表项,再将物理地址和对应的标志位赋给对应的页表项,完成映射。
mips_vm_init
函数完成初始的建立两级页表的任务。首先是用alloc
函数分配一页给页目录;然后分配npage
个Page
给pages
数组,用于管理页面;再将pages
数组这片区域映射到物理内存;类似的,分配空间给envs
进程控制块数组,并映射到对应的物理内存区域。以上都是在启动过程中完成的操作。核心是
mips_vm_init
函数。page_init
函数用于初始化pages
数组并设置page_free_list
数组。首先用LIST_INIT
函数初始化page_free_list
;然后通过freemem
和end
求得已经分配了多少空闲内存;将已分配的内存即freemem
以下的内存以页为单位,通过修改pp_ref
为1的方式记录下来;剩下的内存即freemem
以上的内存则将pp_ref
记为0,并利用LIST_INSERT_HEAD
加入到page_free_list
中。
page_alloc
函数用于分配一页物理内存。首先需要检查是否存在空闲内存,即利用LIST_EMPTY
检查page_free_list
是否为空;然后取出第一项并在链表中删掉这一项;最后将这一项对应的内存清零后返回这一页面控制块。
page_free
函数用来释放一页内存。当pp_ref
为0时将这一页利用LIST_INSERT_HEAD
加入到page_free_list
中。
pgdir_walk
函数类似boot_pgdir_walk
函数,基本思路一样。区别在于,pgdir_walk
函数是在启动之后,所以在需要创建新页表的时候可以使用page_alloc
函数,并且分配后将对应的pp_ref
增加。boot_pgdir_walk
函数由于没有建立页表映射机制,对于pp_ref
是无法操作的。
page_insert
函数用于将物理页映射到特定虚拟地址。首先利用pgdir_walk
函数取得虚拟地址va
的页表项;检查这一页表项是否已经对应到了指定页面上,若页表项不为空且已经映射到了指定页面,则利用tlb_invalidate
更新tlb,然后给对应的页表项赋值并返回;若这一页表项不为空且映射的页面不是指定页面,则需要用page_remove
将这一虚拟地址对应的页面移除;然后利用tlb_invalidate
更新tlb;再一次利用pgdir_walk
函数取得页表项,对这一页表项赋值并增加pp_ref
。
page_lookup
函数用于获得虚拟地址对应的Page
和页表项。首先通过pgdir_walk
得到虚拟地址对应的页表项;如果页表项为空或页表项有效位为0则返回;然后通过pa2page
得到Page
。
page_decref
函数用于减少pp_ref
。
page_remove
函数用于移除物理页面到虚拟地址的映射。首先利用page_lookup
获得Page
和对应的页表项;减少pp_ref
,若pp_ref
为0则需要用page_free
释放掉这一物理页;将页表项清零,并用tlb_invalidate
更新tlb。
tlb_invalidate
函数用于使虚拟地址对应的tlb表项失效,而下次访问这个地址就会触发tlb充填,完成对tlb的更新。核心是调用tlb_out
函数。剩下的三个函数
physical_memory_manage_check
、page_check
、pageout
用于检查以上的内存管理函数功能是否正确。tlb_asm.S
这个文件用于处理tlb更新,即
tlb_out
函数。首先将CP0_ENTRYHI
寄存器的值取出来,将虚拟地址写入;通过tlbp
查找与CP0_ENTRYHI
内容匹配的页表项并写入CP0_INDEX
,由于tlb内部采用流水线设计,因此这条指令后需要执行nop
;若找到则将CP0_ENTRYHI
和CP0_ENTRYLO0
清零,这样在未来对这一虚拟地址进行访问就会诱发tlb充填;利用tlbwi
根据CP0_INDEX
写tlb,然后恢复CP0_ENTRYHI
;若没找到则将CP0_ENTRYHI
恢复为原来的值并返回。
OS-lab2的更多相关文章
- 【bug记录】OS Lab3 踩坑记
OS Lab3 踩坑记 Lab3在之前Lab2的基础上,增加了进程建立.调度和中断异常处理.其中测试包括进程建立以及进程调度部分. 由于是第一次做bug记录,而且是调试完bug后再做的记录,所以导致记 ...
- OS课程 ucore_lab2实验报告
练习零:填写已有实验 本实验依赖实验1.请把你做的实验1的代码填入本实验中代码中有"LAB1"的注释相应部分.提示:可采用diff和patch工具进行半自动的合并(merge ...
- ucore操作系统学习笔记(二) ucore lab2物理内存管理分析
一.lab2物理内存管理介绍 操作系统的一个主要职责是管理硬件资源,并向应用程序提供具有良好抽象的接口来使用这些资源. 而内存作为重要的计算机硬件资源,也必然需要被操作系统统一的管理.最初没有操作系统 ...
- CMU15-455 Lab2 - task4 Concurrency Index -并发B+树索引算法的实现
最近在做 CMU-15-445 Database System,lab2 是需要完成一个支持并发操作的B+树,最后一部分的 Task4 是完成并发的索引这里对这部分加锁的思路和完成做一个总结,关于 B ...
- [OS] 操作系统课程(三)
工具 源码阅读:understand 源码文档自动生成工具:Doxygen 编译环境:gcc 运行环境:x86机器或QEMU 调试工具:QEMU+(GDB or IDE) IDE:Eclipse-CD ...
- MIT6.828 Lab2 内存管理
Lab2 0. 任务介绍 你将编写一个内存管理代码.主要分为两大部分.分别对物理内存和虚拟内存的管理. 对于物理内存,每次分配内存分配器会为你分配4096bytes.也称为一个页(在大部分操作系统中一 ...
- NodeJs之OS
OS Node.js提供了一些基本的底层操作系统的模块OS. API var os = require('os'); console.log('[arch] 操作系统CPU架构'+os.arch()) ...
- Node.js:OS模块
os模块,可以用来获取操作系统相关的信息和机器物理信息,例如操作系统平台,内核,cpu架构,内存,cpu,网卡等信息. 使用如下所示: const os = require('os'); var de ...
- Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验
Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...
- Mac OS 使用 Vagrant 管理虚拟机(VirtualBox)
Vagrant(官网.github)是一款构建虚拟开发环境的工具,支持 Window,Linux,Mac OS,Vagrant 中的 Boxes 概念类似于 Docker(实质是不同的),你可以把它看 ...
随机推荐
- hashlib加密、subprocess、logging日志模块
1.hashlib加密模块 1.加密:将明文数据处理成密文数据,让人无法看懂 2.为什么加密:保证数据的安全 3.如何判断数据是否加密:如果是一长串没有规律的字符串(数字.字母.符号)那么数据被加密 ...
- day08-SpringMVC底层机制简单实现-04
SpringMVC底层机制简单实现-04 https://github.com/liyuelian/springmvc-demo.git 8.任务7-完成简单视图解析 功能说明:通过目标方法返回的 S ...
- 一文看懂 Python 中的函数参数
函数定义中的参数也就是形式参数,规定了在调用函数时如何传递实际参数以及这些参数有无默认值. 实参传递方式 def f(a): print(a) 实参传递方式有两种,位置和关键字.对于上面定义的函数 f ...
- 如何通过C#/VB.NET代码在Word中更改字体颜色
在日常工作中,我们有时会需要修改字体的颜色来突出文本重点,让读者更容易抓住文章要点.在今天这篇文章中,我将为大家介绍如何以编程方式,在Word更改字体颜色.本文将分为两部分分别介绍如何实现此操作.以下 ...
- C++并发-互斥元
1.std::mutex类 1.构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的. 2.lock(),调用线程将锁住 ...
- 剑指 Offer 34. 二叉树中和为某一值的路径(java解题)
目录 1. 题目 2. 解题思路 3. 数据类型功能函数总结 4. java代码 1. 题目 给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总 ...
- 郁金香 注入DLL代码 与MFC窗口DLL文件 开源
10/10号更新 DLL注入器注入DLL卡死 问题 新增打开控制台 将阳光输出到控制台中 注入DLL代码 1 #include <stdio.h> 2 #include<Window ...
- STL中的智能指针(Smart Pointer)及其源码剖析: std::auto_ptr
STL中的智能指针(Smart Pointer)及其源码剖析: std::auto_ptr auto_ptr 是STL中的智能指针家族的成员之一, 它管理由 new expression 获得的对象, ...
- Cesium鼠标移动到模型上,给模型添加高亮轮廓(四)
2023-01-09 Cesium虽然也支持两种方式(Entity和Primitive)加载3D Tiles数据, 但因为多数情况下3D Tiles数据都是成片区的数据,数据量比较大,所以为了保证性能 ...
- 深度学习-LSTM
目录 前言 神经网络的历史和背景 循环神经网络的出现及其作用 LSTM在处理序列数据中的应用 LSTM的基本原理 LSTM的结构和原理 遗忘门.输入门.输出门的作用 LSTM的训练方法 代码 LSTM ...