一步步编写操作系统 38 一级页表与虚拟地址3

接上,页是地址空间的计量单位,并不是专属物理地址或线性地址,只要是4KB的地址空间都可以称为一页,所以线性地址的一页也要对应物理地址的一页。一页大小为4KB,这样一来,4GB地址空间被划分成4GB/4KB=1M个页,也就是4GB空间中可以容纳1048576个页,页表中自然也要有1048576个页表项,这就是我们要说的一级页表。一级页表如图:

这是一级页表模型,由于页大小是4KB,所以页表项中的物理地址都是4k的整数倍,故用16进制表示的地址,低3位都是0。就拿第3个页表项来说,其值为0x3000,表示该页对应的物理地址是0x3000。

可能,您心里一直有个疑问:页表如何使用呢?也就是如何将线性地址转换成物理地址呢?

还是用图5-10帮助理解,滑块正落到在32位地址的第12位。右边11~0位用来表示页的大小,也就是这12位可以做为页内寻址。左边31~12位用来表示页的数量,同样这20位也用来索引一个页(索引范围0~0xfffff),表示第几个页,对吧。

其实也可以这样理解:任意一个地址最终会落到某一个物理页中。32位地址空间共有1M(1048756)个物理页,首先要做的是定位到某个具体物理页,然后给出物理页内的偏移量就可以访问到任意1字节的内存啦。所以,用20位二进制就可以表示全部物理页啦。标准页都是4KB,12位二进制便可以表达4KB之内的任意地址。

在32位保护模式下任何地址都是用32位二进制表示,包括虚拟地址也是。经以上分析,虚拟地址的高20位可用来定位一个物理页,低12位可用来在该物理页内寻址。这是如何实现的呢?物理地址是写在页表的页表项中,段部件输出的只是线性地址,所以问题就变成了:怎样用线性地址找到页表中对应的页表项

在此之前,大家要知道两件事:

  1. 分页机制打开前要将页表地址加载到控制寄存器cr3中,这是启用分页机制的先决条件之一,在介绍二级页表时会细说。所以,在打开分页机制前加载到寄存器cr3中的是页表的物理地址,页表中页表项的地址自然也是物理地址了。
  2. 虽然内存分页机制的作用是将虚拟地址转换成物理地址,但其转换过程相当于在关闭分页机制下进行,过程中所涉及到的页表及页表项的寻址,它们的地址都被cpu当做最终的物理地址(本来也是物理地址)直接送上地址总线,不会被分页机制再次转换(否则会递归转换下去)。

刚才说过啦,如何通过线性地址找到其对应的页表项才是转换的关键。既然页表是位于内存中,所以只要提供页表项的物理地址便能够访问到页表项。页表本身属于线性表结构,相当于页表项数组,访问其中任意页表项成员,只要知道该表页项的索引(下标)就够了。

分析过后,地址转换过程原理如下:

一个页表项对应一个页,所以,用线性地址的高20位做为页表项的索引,每个页表项要占用4字节大小,所以这高20位的索引乘以4后才是该页表项相对于页表物理地址的字节偏移量。用cr3寄存器中的页表物理地址加上此偏移量便是该页表项的物理地址,从该页表项中得到映射的物理页地址,然后用线性地址的低12位与该物理页地址相加,所得的地址之和便是最终要访问的物理地址。

曾经有同学对地址转换过程感到迷惑,误以为启用分页后,页表项地址也是虚拟地址,还需要被转换,转换过程无限递归下去,这显然是不对的。

以上所说的转换步骤多少都有点麻烦,既然地址转换算法已经是固定的了,何不使其在硬件一级自动完成呢。有道理,所以cpu中集成了专门用来干这项工作的硬件模块,我们把该模块称为页部件。当程序中给出一个线性地址时,页部件分析线性地址,按照以上算法,自动在页表中检索到物理地址。

总结一下页部件的工作:用线性地址的高20位在页表中索引页表项,用线性地址的低12位与页表项中的物理地址相加,所求的和便是最终线性地址对应的物理地址。

咱们还是通过例子来理解转换过程吧。拿mov ax,[0x1234]来说,其地址转换完整过程如图:

假设咱们是在平坦模型下工作,不管段选择子值是多少,其所指向的段基址都是0,指令mov ax,[0x1234]中的0x1234称为有效地址,它做为“段基址:段内偏移地址”中的段内偏移地址。这样段基址为0,段内偏移地址为0x1234,经过段部件处理后,输出的线性地址是0x1234。由于咱们是演示分页机制,必须假定系统已经打开了分页机制,所以线性地址0x1234被送入了页部件。页部件分析0x1234的高20位,用16进制表示高20位是0x00001。将此项做为页表项索引,再将该索引乘以4后加上cr3寄存器中页表的物理地址,这样便得到索引所指代的页表项的物理地址,从该物理地址处(页表项中)读取所映射的物理页地址:0x9000。线性地址的低12位是0x234,它做为物理页的页内偏移地址与物理页地址0x9000相加,和为0x9234,这就是线性地址0x1234最终转换成的物理地址。

一级页表说了这么多,完全是为了讲述页表原理,这样就能更好的理解下面要讲的二级页表,它们在原理上一脉相承。因为目前现代操作系统一般都是用二级页表,咱们的系统也采用二级页表,下一节咱们再见啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439723.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Python编程:从入门到实践》速查表

本文是Python畅销书《Python:从入门到实践》速查表。 随书配套视频观看地址:https://www.bilibili.com/video/av35698354 目录 1.Overview 2.Lists 3.Dictionaries 4.If and While Loops 5.Functions 6.Classes 7.Files and Exceptions 8.Testin…

一步步编写操作系统 39 二级页表1

前面讲述了页表的原理,并以一级页表做为原型讲述了地址转换过程。既然有了一级页表,为什么还要搞个二级页表呢?理由如下: 一级页表中最多可容纳1M(1048576)个页表项,每个页表项是4字节&#xf…

PointNet++详解与代码

在之前的一篇文章《PointNet:3D点集分类与分割深度学习模型》中分析了PointNet网络是如何进行3D点云数据分类与分割的。但是PointNet存在的一个缺点是无法获得局部特征,这使得它很难对复杂场景进行分析。在PointNet中,作者通过两个主要的方法…

一步步编写操作系统 40 内存分页下用户程序与操作系统的关系

分页的第一步要准备好一个页表,我们的页表是什么样子呢?现在我们要设计一个页表啦。 设计页表其实就是设计内存布局,不过在规划内存布局之前,我们需要了解用户进程与操作系统之间的关系。 前面讲保护模式时,我们知道…

一步步编写操作系统 41 快表tlb 简介

分页机制虽然很灵活,但您也看到了,为了实现虚拟地址到物理地址的映射,过程还是有些麻烦的。先要从CR3寄存器中获取页目录表物理地址,然后用虚拟地址的高10位乘以4的积做为在页目录表中的偏移量去寻址目录项pde,从pde中…

50个最有用的Matplotlib数据分析与可视化图

本文介绍了数据分析与可视化中最有用的50个数据分析图,共分为7大类:Correlation、Deviation、RankIng、Distribution、Composition、Change、Groups 原文链接:https://www.machinelearningplus.com/plots/top-50-matplotlib-visualizations-t…

视觉SLAM十四讲(1):预备知识

最近在学习高翔博士的《视觉SLAM十四讲》(第二版),算是初学本书,配套资源还算蛮丰富的,有代码(第一版和第二版都有),B站上也有高翔博士对第一版录制的讲解视频,真的是很贴…

一步步编写操作系统 43 汇编语言和c语言的理解

也许有的同学喜欢用汇编语言来实现操作系统,觉得用汇编来写程序似乎更简单直接,可控性比较强,有种“一切尽在掌握”的赶脚。而用c语言实现操作系统这件事,虽然轻松很多,但似乎隐约感觉到有些慌张。因为虽然c语言相对来…

视觉SLAM十四讲(2):初识SLAM

这一讲主要介绍视觉SLAM的结构,并完成第一个SLAM程序:HelloSLAM。 目录 2.1 小萝卜的例子 单目相机 双目相机 深度相机 2.2 经典视觉SLAM框架 2.3 SLAM问题的数学表述 2.4 编程实践 Hello SLAM 使用cmake 使用库 【高翔】视觉SLAM十四讲2.1 小…

一步步编写操作系统 44 用c语言编写内核1

先来个简单的,欢迎我们神秘嘉宾——main.c。这是我们第一个c语言代码。 1 int main(void) { 2 while(1); 3 return 0; 4 }它没法再简单啦,简单的程序似乎能帮助咱们更容易的理解所学的知识,哈哈,我说的是似乎,其实&…

从零实现一个3D目标检测算法(1):3D目标检测概述

本文是根据github上的开源项目:https://github.com/open-mmlab/OpenPCDet整理而来,在此表示感谢,强烈推荐大家去关注。使用的预训练模型也为此项目中提供的模型,不过此项目已更新为v0.2版,与本文中代码略有不同。 本文…

一步步编写操作系统 45 用c语言编写内核2

在linux下用于链接的程序是ld,链接有一个好处,可以指定最终生成的可执行文件的起始虚拟地址。它是用-Ttext参数来指定的,所以咱们可以执行以下命令完成链接: ld kernel/main.o -Ttext 0xc0001500 -e main -o kernel/kernel.bin …

使用OpenCV库快速求解相机内参

本文主要介绍如何使用OpenCV库函数求解相机内参。具体可查阅官网:https://docs.opencv.org/master/dc/dbb/tutorial_py_calibration.html。 关于相机内参的求解还有很多其它的工具,如使用MATLAB求解会更方便,直接调用MATLAB中的APP即可。 1.背…

一步步编写操作系统 46 用c语言编写内核3

再把上节代码贴出来, 1 //int main(void) { 2 int _start(void) { 3 while(1); 4 return 0; 5 }有没有同学想过,这里写一个_start函数,让其调用main函数如何?其实这是可以的,main函数并不是第一个函数,它实…

一步步编写操作系统 47 48 二进制程序运行方式

操作系统并不是在功能上给予用户的支持,这种支持是体现在机制上。也就是说,单纯的操作系统,用户拿它什么都做不了,用户需要的是某种功能。而操作系统仅仅是个提供支持的平台。 虽然我们是模仿linux来写一个黑屏白字的系统&#x…

百度顶会论文复现(1):课程概述

最近百度推出了一款重磅课程《全球顶会论文作者,28天免费手把手带你复现顶会论文》。这个课程真的是很硬核的课程,这里简单记录下自己的学习过程。 文章目录1. 课程设计思路和安排2. 课程大纲1. 课程设计思路和安排 课程设计思路如下,共分为…

百度顶会论文复现(2):GAN综述

本节课主要是对GAN的发展进行了介绍,包括基本原理,训练方法,存在问题,改进以及应用场景等。实践作业则为手写数字生成。课程地址为:https://aistudio.baidu.com/aistudio/education/preview/493290。 文章目录1.什么是…

一步步编写操作系统 48 二进制程序的加载方式

接上节,程序头可以自定义,只要我们按照自己定义的格式去解析就行。也许我光这么一说,很多同学还是不能彻底明白如何自定义文件头,因为大多数同学都是用高级语言来写程序,即使用了偏底层的c语言,不同平台的c…

百度顶会论文复现(3):视频分类综述

本节课主要是对视频分类的发展进行了介绍,包括任务与背景,分类方法,前沿进展等。课程地址为:https://aistudio.baidu.com/aistudio/course/introduce/1340?directly1&shared1。 文章目录1. 任务与背景2. 视频分类方法2.1 双流…

一步步编写操作系统 46 linux的elf可执行文件格式1

ELF文件格式依然是分为文件头和文件体两部分,只是该文件头相对稍显复杂,类似层次化结构,先用个ELF header从“全局上”给出程序文件的组织结构,概要出程序中其它头表的位置大小等信息,如程序头表的大小及位置、节头表的…