MIT 6.828 JOS学习笔记16. Lab 2.2
Part 3 Kernel Address Space
JOS把32位线性地址虚拟空间划分成两个部分。其中用户环境(进程运行环境)通常占据低地址的那部分,叫用户地址空间。而操作系统内核总是占据高地址的部分,叫内核地址空间。这两个部分的分界线是定义在memlayout.h文件中的一个宏 ULIM。JOS为内核保留了接近256MB的虚拟地址空间。这就可以理解了,为什么在实验1中要给操作系统设计一个高地址的地址空间。如果不这样做,用户环境的地址空间就不够了。
Permission and Fault Isolation
由于内核和用户进程只能访问各自的地址空间,所以我们必须在x86页表中使用访问权限位(Permission Bits)来使用户进程的代码只能访问用户地址空间,而不是内核地址空间。否则用户代码中的一些错误可能会覆写内核中的数据,最终导致内核的崩溃。
处在用户地址空间中的代码不能访问高于ULIM的地址空间,但是内核可以读写这部分空间。而内核和用户对于地址范围[UTOP, ULIM]有着相同的访问权限,那就是可以读取但是不可以写入。这一个部分的地址空间通常被用于把一些只读的内核数据结构暴露给用户地址空间的代码。在UTOP之下的地址范围是给用户进程使用的,用户进程可以访问,修改这部分地址空间的内容。
Initializing the Kernel Address Space
现在我们要设置一下UTOP之上的地址空间:这也是整个虚拟地址空间中的内核地址空间部分。inc/memlayout.h文件中已经向你展示了这部分地址空间的布局。你可以使用你刚刚编写的函数来设置这些地址的布局。
Exercise 5
继续完善mem_init()函数,你的程序现在必须能够通过check_kern_pgdir()和check_page_installed_pgdir()函数的检测。
答:
剩下的工作就是要完善mem_init()函数,现在要完善的功能就是把关于操作系统的一些重要的地址范围映射到现在的新页目录项上kern_pgdir上。这里我们可以利用前面定义过的boot_map_region函数。
首先我们要映射的范围是把pages数组映射到线性地址UPAGES,大小为一个PTSIZE。
所以我们添加的代码是:
boot_map_region(kern_pgdir, UPAGES, PTSIZE, PADDR(pages), PTE_U);
其中perm变量之所以设置为PTE_U,是因为这部分空间是kernel space和user space中的代码都能访问的,所以要设置PTE_U。
然后映射内核的堆栈区域,把由bootstack变量所标记的物理地址范围映射给内核的堆栈。内核堆栈的虚拟地址范围是[KSTACKTOP-PTSIZE, KSTACKTOP),不过要把这个范围划分成两部分:
* [KSTACKTOP-KSTKSIZE, KSTACKTOP) 这部分映射关系加入的页表中。
* [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) 这部分不进行映射。
对这部分地址的访问权限是,kernel space 可以读写,user space 无权访问,所以代码如下:
boot_map_region(kern_pgdir, KSTACKTOP - KSTKSIZE, KSTKSIZE, PADDR(bootstack), PTE_W)
最后映射整个操作系统内核,虚拟地址范围是[KERNBASE, 2^32],物理地址范围是[0,2^32 - KERNBASE]。
访问权限是,kernel space 可以读写,user space 无权访问,所以代码如下:
boot_map_region(kern_pgdir, KERNBASE, 0xffffffff - KERNBASE, , PTE_W);
至此,Exercise 5已经全部完成。
Question:
2. 到目前为止页目录表中已经包含多少有效页目录项?他们都映射到哪里?
3BD号页目录项,指向的是kern_pgdir
3BC号页目录项,指向的是pages数组
3BF号页目录项,指向的是bootstack
3C0~3FF号页目录项,指向的是kernel
3. 如果我们把kernel和user environment放在一个相同的地址空间中。为什么用户程序不同读取,写入内核的内存空间?用什么机制保护内核的地址范围。
用户程序不能去随意修改内核中的代码,数据,否则可能会破坏内核,造成程序崩溃。
正常的操作系统通常采用两个部件来完成对内核地址的保护,一个是通过段机制来实现的,但是JOS中的分段功能并没有实现。二就是通过分页机制来实现,通过把页表项中的 Supervisor/User位置0,那么用户态的代码就不能访问内存中的这个页。
4. 这个操作系统的可以支持的最大数量的物理内存是多大?
由于这个操作系统利用一个大小为4MB的空间UPAGES来存放所有的页的PageInfo结构体信息,每个结构体的大小为8B,所以一共可以存放512K个PageInfo结构体,所以一共可以出现512K个物理页,每个物理页大小为4KB,自然总的物理内存占2GB。
5. 如果现在的物理内存页达到最大个数,那么管理这些内存所需要的额外空间开销有多少?
这里不太明白,参考别的答案是,首先需要存放所有的PageInfo,需要4MB,需要存放页目录表,kern_pgdir,4KB,还需要存放当前的页表,大小为2MB。所以总的开销就是6MB + 4KB。
6. 回顾entry.S文件中,当分页机制开启时,寄存器EIP的值仍旧是一个小的值。在哪个位置代码才开始运行在高于KERNBASE的虚拟地址空间中的?当程序位于开启分页之后到运行在KERNBASE之上这之间的时候,EIP的值是小的值,怎么保证可以把这个值转换为真实物理地址的?
在entry.S文件中有一个指令 jmp *%eax,这个指令要完成跳转,就会重新设置EIP的值,把它设置为寄存器eax中的值,而这个值是大于KERNBASE的,所以就完成了EIP从小的值到大于KERNBASE的值的转换。
在entry_pgdir这个页表中,也把虚拟地址空间[0, 4MB)映射到物理地址空间[0, 4MB)上,所以当访问位于[0, 4MB)之间的虚拟地址时,可以把它们转换为物理地址。
Address Space Layout Alternatives
进程的虚拟地址空间的布局不是只有我们讨论的这种唯一的情况,我们也可以把内核映射到低地址处。但是JOS之所以要这么做,是为了保证x86的向后兼容性。
只要我们能够仔细设计,虽然很难,但是我们也能设计出来一种内核的布局方式,使得进程的地址空间就是从0到4GB,无需为内核预留一部分空间,但是仍然能够保证,用户进程不会破坏操作系统的指令,数据。
至此,lab 2已经全部完成~欢迎大家的意见与问题
zzqwf12345@163.com
MIT 6.828 JOS学习笔记16. Lab 2.2的更多相关文章
- MIT 6.828 JOS学习笔记2. Lab 1 Part 1.2: PC bootstrap
Lab 1 Part 1: PC bootstrap 我们继续~ PC机的物理地址空间 这一节我们将深入的探究到底PC是如何启动的.首先我们看一下通常一个PC的物理地址空间是如何布局的: ...
- MIT 6.828 JOS学习笔记15. Lab 2.1
Lab 2: Memory Management lab2中多出来的几个文件: inc/memlayout.h kern/pmap.c kern/pmap.h kern/kclock.h kern/k ...
- MIT 6.828 JOS学习笔记10. Lab 1 Part 3: The kernel
Lab 1 Part 3: The kernel 现在我们将开始具体讨论一下JOS内核了.就像boot loader一样,内核开始的时候也是一些汇编语句,用于设置一些东西,来保证C语言的程序能够正确的 ...
- MIT 6.828 JOS学习笔记7. Lab 1 Part 2.2: The Boot Loader
Lab 1 Part 2 The Boot Loader Loading the Kernel 我们现在可以进一步的讨论一下boot loader中的C语言的部分,即boot/main.c.但是在我们 ...
- MIT 6.828 JOS学习笔记1. Lab 1 Part 1: PC Bootstrap
Lab 1: Booting a PC Part 1: PC Bootstrap 介绍这一部分知识的目的就是让你能够更加熟悉x86汇编语言,以及PC启动的整个过程,而且也会首次学习使用QEMU软件来仿 ...
- MIT 6.828 JOS学习笔记18. Lab 3.2 Part B: Page Faults, Breakpoints Exceptions, and System Calls
现在你的操作系统内核已经具备一定的异常处理能力了,在这部分实验中,我们将会进一步完善它,使它能够处理不同类型的中断/异常. Handling Page Fault 缺页中断是一个非常重要的中断,因为我 ...
- MIT 6.828 JOS学习笔记17. Lab 3.1 Part A User Environments
Introduction 在这个实验中,我们将实现操作系统的一些基本功能,来实现用户环境下的进程的正常运行.你将会加强JOS内核的功能,为它增添一些重要的数据结构,用来记录用户进程环境的一些信息:创建 ...
- MIT 6.828 JOS学习笔记4. Lab 1 Part 2.1: The Boot Loader
Part 2: The Boot Loader 对于PC来说,软盘,硬盘都可以被划分为一个个大小为512字节的区域,叫做扇区.一个扇区是一次磁盘操作的最小粒度.每一次读取或者写入操作都必须是一个或多个 ...
- MIT 6.828 JOS学习笔记0. 写在前面的话
0. 简介 操作系统是计算机科学中十分重要的一门基础学科,是一名计算机专业毕业生必须要具备的基础知识.但是在学习这门课时,如果仅仅把目光停留在课本上一些关于操作系统概念上的叙述,并不能对操作系统有着深 ...
随机推荐
- javascript 日期操作
1.获取指定年月有多少周 /** * 获得一个月的周数 * @param {} y {xxxx}4位数 * @param {} m {0-11} * @return {} */ function ge ...
- Linux C++中的时间函数(转)
http://net.pku.edu.cn/~yhf/linux_c/function/03.html asctime(将时间和日期以字符串格式表示) 相关函数 time,ctime,gmtime ...
- SqlServer 常用函数
case .. when .. then .. else .. end
- KMP专题
1.[HDU 3336]Count the string(KMP+dp) 题意:求给定字符串含前缀的数量,如输入字符串abab,前缀是a.ab.aba.abab,在原字符串中出现的次数分别是2.2.1 ...
- codility flags solution
How to solve this HARD issue 1. Problem: A non-empty zero-indexed array A consisting of N integers i ...
- wxPython 自动提示文本框
1.原版和例子都在这里 在浏览器的地址栏,或者在百度.google 输入文字的时候,输入框的下面会把有关的项目都提示出来. wxPython 没有提供类似的控件,google 了一下,发现了一个,很好 ...
- Spark 官方文档(2)——集群模式
Spark版本:1.6.2 简介:本文档简短的介绍了spark如何在集群中运行,便于理解spark相关组件.可以通过阅读应用提交文档了解如何在集群中提交应用. 组件 spark应用程序通过主程序的Sp ...
- 页面滚动到底部自动 Ajax 获取文章
页面滚动到底部自动 Ajax 获取文章 代码如下 复制代码 var _timer = {};function delay_till_last(id, fn, wait) { if (_time ...
- Maven的POM.xml配置大全
<?xml version="1.0" encoding="utf-8"?> <project xmlns="http://mave ...
- Java中的24种设计模式与7大原则
一.创建型模式 1.抽象工厂模式(Abstract factory pattern): 提供一个接口, 用于创建相关或依赖对象的家族, 而不需要指定具体类.2.生成器模式(Builder patter ...