MIT 6.828 | JOS | 关于虚拟空间和物理空间的总结
Question:
做lab过程中越来越迷糊,为什么一会儿虚拟地址是4G 物理地址也是4G ,那这有什么作用呢?
解决途径:
停下来,根据当前lab的进展,再回头看上学期操作系统的ppt & 上网冲浪查资料!意识到自己对于分段机制
理解不够。
最强总结:https://www.cnblogs.com/tolimit/p/4775945.html?utm_source=tuicool&utm_medium=referral
解决过程:
分段机制主要功能只有两点:
- 将物理内存划分为多个段,让操作系统可以使用大于其地址线对应的物理内存(比如正常情况下32位地址线可以访问4G大小的内存,但是有分段后则可访问大于4G的内存)。
- 权限控制,将每个段设置权限位,让不同的程序访问不同的段。
linux内核只用到了权限控制的功能,但是我一直将其理解为第一个功能!!!
注意:JOS中的分段功能并没有实现
正常的操作系统通常采用两个部件来完成对内核地址的保护,一个是通过段机制来实现的,但是JOS中的分段功能并没有实现。二就是通过分页机制来实现,通过把页表项中的 Supervisor/User位置0,那么用户态的代码就不能访问内存中的这个页。
物理地址空间
+------------------+ <- 0xFFFFFFFF (4GB)
| 32-bit |
| memory mapped |
| devices |
| |
/\/\/\/\/\/\/\/\/\/\
/\/\/\/\/\/\/\/\/\/\
| |
| Unused |
| |
+------------------+ <- depends on amount of RAM
| |
| |
| Extended Memory |
| |
| |
+------------------+ <- 0x00100000 (1MB)
| BIOS ROM |
+------------------+ <- 0x000F0000 (960KB)
| 16-bit devices, |
| expansion ROMs |
+------------------+ <- 0x000C0000 (768KB)
| VGA Display |
+------------------+ <- 0x000A0000 (640KB)
| |
| Low Memory |
| |
+------------------+ <- 0x00000000
GDT/LDT && 分段机制
采用的方式就是引入了数据结构GDT,即全局描述符表,不知道有多少人听过?说简单点,GDT就是一个数组,每一个元素就是一个描述符,多个组合一起就构成了全局描述符表。而每一个描述符共64位,包含了以下的这些信息:段基址、段长度、属性。原来的段寄存器,比如CS,DS等存的值则不是段偏移了,而是GDT的索引,通过该索引就可以找到对应的描述符。现在是不是明白了呢?接下来我们再详细的解释一下一个描述符中各个位的意义吧。
LDT 可以看作是多级索引的第二级GDT。

![]()
Linux 4种段寄存器取值
也就是linux只有4种段的选择。
![]()
![]()
保护模式地址映射
从实模式切换到保护模式
1、准备GDT
2、用lgdt指令加载gdtr
3、打开A20地址线
4、将cr0寄存器的最后一位(PE位)置1:
PE位为0时,CPU运行在实模式下;
PE位为1时,CPU运行在保护模式下.
5、跳转,进入保护模式
bootloader为止的模型
物理内存的分布
Lab1进入内存后,开启分页模式,将虚拟地址[0, 4MB)映射到物理地址[0, 4MB),[0xF0000000, 0xF0000000+4MB)映射到[0, 4MB)(/kern/entry.S)
lab1 结束后物理分布如下:
- lab2 中mem_init()结束之后,物理地址分布如下:
终极问题:物理空间和虚拟空间都是4G,为什么分布不一样?
这个问题困扰了我很久,并且在迷迷糊糊做lab的时候没有搞明白。
在总结梳理了前面的知识之后,终于可以解决这个问题了!
参考:
MIT 6.828 Lab Guide
CPU访问内存之后,就可以向其他kernel的其它模块、内核线程、用户空间进程、等等)提供服务,主要包括:
- 以虚拟地址(VA)的形式,为应用程序提供远大于物理内存的虚拟地址空间(Virtual Address Space)
- 每个进程都有独立的虚拟地址空间,不会相互影响,进而可提供非常好的内存保护(memory protection)
- 提供内存映射(Memory Mapping)机制,以便把物理内存、I/O空间、Kernel Image、文件等对象映射到相应进程的地址空间中,方便进程的访问
- 提供公平、高效的物理内存分配(Physical Memory Allocation)算法
- 提供进程间内存共享的方法(以虚拟内存的形式),也称作Shared Virtual Memory
在提供这些服务之前需要对内存进行合理的划分和管理。
物理地址空间布局
Linux系统在初始化时,会根据实际的物理内存的大小,为每个物理页面创建一个page对象,所有的page对象构成一个mem_map数组。进一步,针对不同的用途,Linux内核将所有的物理页面划分到3类内存管理区中,如图,分别为ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM。
- ZONE_DMA 的范围是 0~16M,该区域的物理页面专门供 I/O 设备的 DMA 使用。之所以需要单独管理 DMA 的物理页面,是因为 DMA 使用物理地址访问内存,不经过 MMU,并且需要连续的缓冲区,所以为了能够提供物理上连续的缓冲区,必须从物理地址空间专门划分一段区域用于 DMA。
- ZONE_NORMAL 的范围是 16M~896M,该区域的物理页面是内核能够直接使用的。
- ZONE_HIGHMEM 的范围是 896M~结束,该区域即为高端内存,内核不能直接使用。
Linux内核空间虚拟地址分布
在 Kernel Image 下面有 16M 的内核空间用于 DMA 操作。位于内核空间高端的 128M 地址主要由3部分组成,分别为 vmalloc area、持久化内核映射区、临时内核映射区。
由于 ZONE_NORMAL 和内核线性空间存在直接映射关系,所以内核会将频繁使用的数据如 Kernel 代码、GDT、IDT、PGD、mem_map 数组等放在 ZONE_NORMAL 里。而将用户数据、页表(PT)等不常用数据放在 ZONE_HIGHMEM 里,只在要访问这些数据时才建立映射关系(kmap())。比如,当内核要访问 I/O 设备存储空间时,就使用 ioremap() 将位于物理地址高端的 mmio 区内存映射到内核空间的 vmalloc area 中,在使用完之后便断开映射关系。
Linux用户空间虚拟地址分布
用户进程的代码区一般从虚拟地址空间的 0x08048000 开始,这是为了便于检查空指针。代码区之上便是数据区,未初始化数据区,堆区,栈区,以及参数、全局环境变量。
Linux物理地址和虚拟地址的关系
Linux 将 4G 的线性地址空间分为2部分,0~3G 为 user space,3G~4G 为 kernel space。
【超级重要】
由于开启了分页机制,内核想要访问物理地址空间的话,必须先建立映射关系,然后通过虚拟地址来访问。为了能够访问所有的物理地址空间,就要将全部物理地址空间映射到 1G 的内核线性空间中,这显然不可能。于是,内核将 0~896M 的物理地址空间一对一映射到自己的线性地址空间中,这样它便可以随时访问 ZONE_DMA 和 ZONE_NORMAL 里的物理页面;此时内核剩下的 128M 线性地址空间不足以完全映射所有的 ZONE_HIGHMEM,Linux 采取了动态映射的方法,即按需的将 ZONE_HIGHMEM 里的物理页面映射到 kernel space 的最后 128M 线性地址空间里,使用完之后释放映射关系,以供其它物理页面映射。虽然这样存在效率的问题,但是内核毕竟可以正常的访问所有的物理地址空间了。
总结如下:
总结JOS 的虚拟空间和物理空间对应关系
做完实验后,我将与虚拟空间和物理空间有关的内容进行了梳理,画出了下图:
1、[UPAGES, UVPT]: 在虚拟地址中的这段内存就是对应的在实际物理地址里 pages 数组的存储位置。可以看到这段地址在ULIM之下,也就是说操作系统开放pages数组便于让用户程序可以访问。为什么呢?比如说假如有的程序想要知道一个物理页面被引用了多少次,那么根据相应的pages[i].pp_ref就可以知道了。我们看到这个区域在布局中分配了 PTSIZE 的大小,那么这个大小够么?因为我们知道在物理页面中pages所占用的大小为npage × sizeof (struct PageInfo) =npage ×8B(使用sizeof()查看,一个指针占4字节,uint16_t是2个字节,可是struct PageInfo占8字节,有些迷惑,可借鉴uint16_t类型在 Bochs 模拟出来的 x86 平台上是4字节理解)。我们看看PTSIZE的空间可以装struct Page的个数为1024 ×4KB / 8B = 4MB / 8B = 1/2M。一个Page结构对应一个实际大小为4KB的物理页面,所以这个PTSIZE大小的虚拟地址空间能够管理 1/2 M × 4KB =2GB的物理内存,这个对于我们的QEMU模拟器来讲应该还是足够了。
2、[UVPT, ULIM]: 这部分是一个系统页目录——kern_pgdir。开放给用户只读,可以使用户得到当前内存中某个虚拟地址对应的物物理页面地址是多少。关于这部分,我们需要看一下:
kern/pmap.c
kern_pgdir这部分实际紧接在kernel 的 end 后面,也即在实际的物理地址里,上图最下面一句话使以物理地址 PADDR(kern_pgdir) 开始的一页成为了虚拟地址的 PDX = PDX(UVPT) 的页表。这部分实际占物理空间 PGSIZE, 但是在虚拟地址上却分配了 PTSIZE 大小。
注意 UVPD 的虚拟地址为 PDX(UVPT)<<22 | PDX(UVPT)<<12 | 0000000000 。
详细的 UVPT 介绍见:Lecture 5
3、[KERNBASE, 4G] : 此部分映射实际物理内存中从0开始的中断向量表IDT、BIOS程序、IO端口以及操作系统内核等,该部分虚拟地址 - KERNBASE 就是物理地址。
从这个布局结构我们就可以看出来,实际上虚拟内存中分配给用户的只有[0, ULIM)大概3.7GB而非4GB的空间(ULIM = 0xef800000),其余的空间需要分配给操作系统。
MIT 6.828 | JOS | 关于虚拟空间和物理空间的总结的更多相关文章
- 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学习笔记17. Lab 3.1 Part A User Environments
Introduction 在这个实验中,我们将实现操作系统的一些基本功能,来实现用户环境下的进程的正常运行.你将会加强JOS内核的功能,为它增添一些重要的数据结构,用来记录用户进程环境的一些信息:创建 ...
- 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学习笔记0. 写在前面的话
0. 简介 操作系统是计算机科学中十分重要的一门基础学科,是一名计算机专业毕业生必须要具备的基础知识.但是在学习这门课时,如果仅仅把目光停留在课本上一些关于操作系统概念上的叙述,并不能对操作系统有着深 ...
- MIT 6.828 JOS学习笔记16. Lab 2.2
Part 3 Kernel Address Space JOS把32位线性地址虚拟空间划分成两个部分.其中用户环境(进程运行环境)通常占据低地址的那部分,叫用户地址空间.而操作系统内核总是占据高地址的 ...
- MIT 6.828 JOS学习笔记12 Exercise 1.9
Lab 1中Exercise 9的解答报告 Exercise 1.9: 判断一下操作系统内核是从哪条指令开始初始化它的堆栈空间的,以及这个堆栈坐落在内存的哪个地方?内核是如何给它的堆栈保留一块内存空间 ...
- 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学习笔记18. Lab 3.2 Part B: Page Faults, Breakpoints Exceptions, and System Calls
现在你的操作系统内核已经具备一定的异常处理能力了,在这部分实验中,我们将会进一步完善它,使它能够处理不同类型的中断/异常. Handling Page Fault 缺页中断是一个非常重要的中断,因为我 ...
随机推荐
- Spring Cloud Alibaba教程:Nacos
Nacos是什么 Nacos 致力于帮助您发现.配置和管理微服务,它 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理. 注册中心 nacos-server 可以 ...
- 关于SignalR 进行双向多步对话
关于ASP.NET SignalR 解释百度百科是这样说的: ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程.实时 ...
- 网络通信机制:Socket、TCP/IP、HTTP
13.1.1 TCP/IP协议 讲的很抽象,没具体看懂什么是TCP协议,什么是IP协议.IP协议保证消息从一个主机传送到另一个主机,消息在传送的过程中被分割成一个个小包,TCP协议会让两台相互连接的计 ...
- django表单使用
一.表单常用字段类型及参数 表单可以自动生成html代码,每一个字段默认有一个html显示样式,大多数默认为输入框. 字段相当于正则表达式的集合,能够对表单传入的数据进行校验,并且某一部分校验失败时会 ...
- python学习笔记1 -- 函数式编程之高阶函数 使用函数作为返回值
使用函数作为返回值,看起来就很高端有木有,前面了解过函数名本身就是一个变量,就比如abs()函数,abs只是变量名,而abs()才是函数调用,那么我们如果把ads这个变量作为返回值返回会怎么样呢,这就 ...
- Java语言概述_章节练习题及面试
学于尚硅谷开源课程 宋洪康老师主讲 感恩 尚硅谷官网:http://www.atguigu.com 尚硅谷b站:https://space.bilibili.com/302417610?from=se ...
- PHP fileatime() 函数
定义和用法 fileatime() 函数返回指定文件的上次访问时间. 如果成功,该函数将以 Unix 时间戳形式返回文件的上次访问时间.如果失败,则返回 FALSE. 语法 fileatime(fil ...
- Echarts饼图绘制
实现效果: html代码: <div id="chartBody1" style="width:120%;height:28vh;"> <di ...
- luogu3706 [SDOI2017]硬币游戏
LINK:硬币游戏 对于40分的暴力 构造出AC自动机 列出转移矩阵 暴力高消.右转上一篇文章. 对于100分 我们不难想到这个矩阵过大 且没有用的节点很多我们最后只要n个节点的答案 其他节点的答案可 ...
- Servlet容器启动过程
参考:https://blog.csdn.net/fredaq/article/details/9366043 一.概念 所谓Servlet容器其实说白了是符合Servlet规范的Java web容器 ...