MIT jos 6.828 Fall 2014 训练记录(lab 2)
注: 源代码参见我的github:https://github.com/YaoZengzeng/jos
Part1 : Physical Page Management
mem_init函数:
/*该函数主要用于建立一个二级页表:kern_pgdir是该页表的虚拟地址
该函数只用于内核地址空间的内存管理(address >= UTOP),用户地址空间部分会在之后进行处理
从UTOP到ULIM的区域用户可以读取但不能写,高于ULIM的区域,用户既不能读也不能写*/
主执行流程:
(1)i386_detect_memory():检测机器的内存数目,npages->物理内存页总数,npages_basemem->base memory的总数
(2)kern_pgdir = (pde_t *) boot_alloc(PGSIZE): 创建初始页目录
(3)kern_pgdir[PDX(UVPT)] = PADDR(kern_pgdir) | PTE_U | PTE_P;
(4)pages = (struct PageInfo *) boot_alloc(npages * sizeof(struct PageInfo));
memset(pages, 0, npages * sizeof(struct PageInfo));
分配一系列struct PageInfo用于记录物理页的状态
(5)page_init():将空闲页加入page_free_list,之后就可以通过page_*函数对内存进行操作
Part2: Virtual Memory
1、页转换(Page Translation)
只有在CR0寄存器的PG位置位时,页转换才会进行。这个位是在操作系统进行初始化的时候进行设置的。


线性地址到物理地址的转换步骤如下:
(1)当前page directory 的物理地址一般存放在CPU的CR3寄存器(也叫page directory base register (PDBR))中
(2)Page Directory = 1024 * Dir Entry, 每个Dir Entry 指向一个Page Table, 通过线性地址的DIR部分找到相应的Page Table
(3)Page Table = 1024 * Page Table Entry,每个Page Table Entry 指向一个物理页,通过线性地址的PAGE部分找到相应的物理页
(4)从Page Table Entry中获取Page Frame 的基地址,再结合线性地址的OFFSET,找到线性地址对应的物理地址

如果Present位为0,不管是在Page Directory 或是Page Table,都会产生一个page exception,之后 page-not-present exception handler会分配相应的物理页。之后,造成缺页异常的指令会被重新执行。
2、在x86中,virtual address由segment selector和offset组成。linear address是virtual address经过segment translation得到的,之后linear address通过page translation转换为physical address.
3、在C语言中的指针通常就是virtual address中的offset。但是,在boot/boot.S中,我们安装了一个Global Descriptor Table通过将所有segment base addresses设置为0到0xffffff,从而禁止segment translation。因此在这个实验中,“selector”没有任何作用,linear address总是和virtual address的offset相等。
4、一旦我们进入保护模式之后,我们就不能直接访问linear address或者physical address,所有的内存访问都会通过MMU的转换,因此所有指针都是virtual address,也就是说通过kernel访问的地址都是virtual address,而不能直接访问physical address。在JOS中,uintptr_t类型的变量代表的是virtual address,physaddr_t类型的变量代表的是physical addresses。
5、JOS将physical address 0 映射到virtual address 0xf0000000的一个原因是,当kernel只知道physical address时,加上0xf0000000即可得到对应的virtual address(使用宏KADDR(pa)),同理,将virtual address减去0xf0000000即可得到对应的physical address(使用宏PADDR(va))。
6、
(1)pte_t* pgdir_walk(pde_t *pgdir, const void *va, int create):根据地址va找到相应的page table entry(PTE),当create为true且相应的page table不存在,则分配一个page作为page table,然后返回相应的PTE。
(2)struct PageInfo* page_alloc(int alloc_flag):获取一个物理页,但是该页的引用依旧为0。
(3)void page_free(struct PageInfo *pp):将pp返回空页链表,当前仅当该页的引用为0时。
(4)int page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm):将virtual address va映射到pp。当va已经被映射时,先将原来的映射的物理页删除,再进行操作。若va之前映射的物理页和pp是同一个页,则仅仅只是改变页面的访问权限perm而已。
(5)void page_remove(pde_t *pgdir, void *va):将va与对应的物理页解除映射关系,如果va并没有映射物理页,则什么都不做。
(6)struct PageInfo* page_lookup(pde_t *pgdir, void* va, pte_t **pte_store):返回virtual address va对应的物理页,如果pte_store不为NULL则,将va对应的PTE也存放到pte_store中。该函数一般被page_remove使用,或者被用来验证页表的访问权限。
(7)static void boot_map_region(pde_t *pgdir, uintptr_t va, size_t size, physaddr_t pa, int perm):该函数用来在page table 中将[va, va+size)范围内的virtual address映射到[pa, pa+size)范围内的物理地址。该函数只能用来做高于UTOP的“静态”映射。
Part3:Kernel Address Space
1、在inc/memlayout.h中的ULIM将内存分为上下两部分,其中上部分大约256MB的内存为kernel的地址空间,下部分则作为用户空间,由user processes使用。
2、因为每个进程都包含用户地址空间和内核地址空间,因此,我们需要在页表中设置相应的权限保证使得用户的代码只能访问用户空间。否则,用户代码的bug可能会覆写内核数据,导致内核崩溃,甚至窃取其他进程的私有数据。用户进程对于ULIM以上的地址没有任何权限。对于[UTOP, ULIM]内的地址,内核进程和用户进程有相同的权限:只能读不能写。这部分的地址空间是内核暴露一些数据结构供用户进程使用的。
MIT jos 6.828 Fall 2014 训练记录(lab 2)的更多相关文章
- MIT jos 6.828 Fall 2014 训练记录(lab 6)
源代码参见我的github: https://github.com/YaoZengzeng/jos 在这个实验中将实现一个基于Intel 82540M(又称E1000)的网卡驱动.不过,一个网卡驱动还 ...
- MIT jos 6.828 Fall 2014 训练记录(lab 4)
源代码参见我的github: https://github.com/YaoZengzeng/jos Part A: Multiprocessor Support and Cooperative Mul ...
- MIT jos 6.828 Fall 2014 训练记录(lab 1)
注: 源代码参见我的github:https://github.com/YaoZengzeng/jos Part 1: PC Bootstrap +------------------+ <- ...
- MIT jos 6.828 Fall 2014 训练记录(lab 5)
源代码参见我的github: https://github.com/YaoZengzeng/jos File system perliminaries 我们开发的是一个单用户的操作系统,只提供了足够的 ...
- MIT jos 6.828 Fall 2014 训练记录(lab 3)
注:源代码参见我的github: https://github.com/YaoZengzeng/jos Part A : User Environments and Exception Handlin ...
- MIT 操作系统实验 MIT JOS lab2
MIT JOS lab2 首先把内存分布理清楚,由/boot/main.c可知这里把kernel的img的ELF header读入到物理地址0x10000处 这里能够回想JOS lab1的一个小问.当 ...
- 台州学院maximum cow训练记录
前队名太过晦气,故启用最大牛 我们的组队大概就是18年初,组队阵容是17级生詹志龙.陶源和16级的黄睿博. 三人大学前均无接触过此类竞赛,队伍十分年轻.我可能是我们队最菜的,我只是知道的内容最多,靠我 ...
- MIT 操作系统实验 MIT JOS lab1
JOS lab1 首先向MIT还有K&R致敬! 没有非常好的开源环境我不可能拿到这么好的东西. 向每个与我一起交流讨论的programmer致谢!没有道友一起死磕.我也可能会中途放弃. 跟丫死 ...
- MIT JOS学习笔记03:kernel 02(2016.11.08)
未经许可谢绝以任何形式对本文内容进行转载! 本篇接着上一篇对kernel的分析. (5)pte_t * pgdir_walk(pde_t *pgdir, const void *va, int cre ...
随机推荐
- 与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复
[源码下载] 与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复 作者:webabcd 介绍与众不同 win ...
- 行转列一定要sum
--SELECT 姓名 ,-- 课程 ,-- 分数--FROM tb UNPIVOT ( 分数 FOR 课程 IN ( [语文], [数学], [物理] ) ) t --)
- The type java.util.Map$Entry cannot be resolved. It is indirectly referenced。。.相似的错误
这个问题是出现一般都是因为JDK版本的问题.今天公司安装NC的时候就出现了这个问题.经过对错误的分析和猜测,将JDK从1.8i换成了1.7,之后就行了.根据我个人的猜测,可能是1.8以后就不支持Map ...
- YII 的基本CURL操作
Order::model()->updateAll(array('merchant_id'=>'bbb'), "id in ('140868169311','1408690584 ...
- [maven] 生命周期和插件
maven生命周期和插件 生命周期 maven的生命周期有三套,互相独立.每个生命周期含有不同阶段,常用如下 clean 清理项目 pre-clean 执行清理前需要完成的工作 clean 清理上一次 ...
- Erlang进程间消息接收超时设定
Erlang消息接收函数,一般都会设计成尾递归调用自己的模式.但是这样的模式,如果没有消息则会无限的等待下去,所以为了不无限等待,这里可以加个超时设定,例如: flush() -> re ...
- thinkPHP学习笔记(1)
现在对前端的要求越来越高了 基本上身为一个前端人员需要会一种后台语言,于是选择了当下流行的php.因为是自学对我这个不怎么懂代码的人来说还是有点难度的. 1.先看看thinkphp的目录结构 ├─T ...
- 【转】内部Handler类引起内存泄露
如果您在Activity中定义了一个内部Handler类,如下代码: public class MainActivity extends Activity { private Handl ...
- Android 网络编程基础之简单聊天程序
前一篇讲了Android的网络编程基础,今天写了一个简单的聊天程序分享一下 首先是服务端代码: package com.jiao.socketdemo; import java.io.Buffered ...
- 敏捷软件开发:原则、模式与实践——第8章 SRP:单一职责原则
第8章 SRP:单一职责原则 一个类应该只有一个发生变化的原因. 8.1 定义职责 在SRP中我们把职责定义为变化的原因.如果你想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责.同时,我 ...