Linux内核启动(理论,0.11版本)分段与分页

news2024/11/18 12:40:34

为什么要虚拟内存

我们知道,在之前上微机原理时,我们的程序是可以直接访问内存的,而且访问的是直接的物理内存,在实模式下,寄存器是16位的,数组总线(data bus)是16位的,但地址总线是20位的,这带来了一个问题,需要两个寄存器去访问一个数据,为什么地址中心不是16位呢,那样不就好了,不是不想,是不够用啊,16位的地址总线才能访问64KB内存。所以用CS:IP两个寄存器去访问内存。

这样做有什么问题呢,碎片。碎片分为内部碎片和外部碎片,内部碎片是指已经被分配但是没有被使用的地址空间,比如你申请了7bit但是内存为了对齐不得不给你分配8bit的空间,这就产生了1bit的碎片,外部碎片是指未分配且未使用的地址空间,申请4字节的Int类型,再申请8字节的long类型,为了内存对齐,其中4字节无法装入8字节类型,这就产生了4字节的外部碎片。

内部碎片是已经被分配的内存,是操作系统不可以利用的空间,但是外部碎片是未被分配的,但是该空间过小,无法装载资源,无法被利用,外部碎片是可以解决的。

为了解决内存的碎片化问题,计算机专家们提出了分段式管理的思想,但是再说分段之前需要说一下早期的虚拟内存模型

早期虚拟内存模型

在经历了纯物理地址后,科学家们期望解决这种内存模型难以统一的问题,于是虚拟内存技术孕育而生,但困扰科学家们的是,如何将虚拟地址转换成物理地址。早期的科学家想到的是将整个程序作为一个整体,并为每个进程分配一个基址寄存器和界限寄存器,基址寄存器存放该虚拟地址在实际物理地址的起点,界限寄存器用来判定程序是否访问非法地址,通过这种方式,实际的地址是很好计算的(实际地址=虚拟地址+基址),这种方式虽然解决了地址翻译问题,但是产生了大量的内部碎片。

请添加图片描述

从图中可以看出,如果我们将整个地址空间放入物理内存,那么栈和堆之间的空间并没有被进程使用,却依然占用了实际的物理内存。因此,简单的通过基址寄存器和界限寄存器实现的虚拟内存很浪费。

另外,我们必须要确保内存足够放得下进程的虚拟地址空间,但通常主存成本是比较昂贵的,不如磁盘廉价,这种方式通常不支持大的虚拟地址,如果剩余物理内存无法提供连续区域来放置完整的地址空间,进程便无法运行。例如现在32位的进程空间通常是4GB,主存根本就装不下几个进程。

所以我们需要物尽其用,早起的科学家们想到了分段这种思想

分段式管理的思想

分段思想其实就是将基址加界限的概念泛化,在上述例子中,我们为代码、堆、栈分别设置一个段基址加段界限寄存器,这样我们不必要每次都强制装入整个进程空间,每个基址寄存器存放在该段在物理地址的实际空间,界限寄存器用来保护地址空间,对程序未使用的空间我们没必要为其分配,我们仍需要为堆分配较多的内存,除了堆段,其余空间都是在编译期间就确定了的,这样便大大提高了内存的利用率,而且我们发现可以离散的分配内存空间,即物理内存中的地址不必要时连续的,能大大提高对物理地址的利用率。

请添加图片描述

分段地址的转换

分段式的思想讲完了,但是还有一些问题,地址怎么转换,其实分段地址转换与基址加界限的思想差不多,操作系统通过维护一个段表来维护各段的信息

请添加图片描述

段表的地址是操作系统维护的,段表项主要维护段长和段基址,段基址指该段在物理内存中的起始地址,那么该段中的虚拟地址对于实际地址为 段基址+段内偏移

分段系统的逻辑地址结构是段号(段名) 和 段内地址(段内偏移量)组成的,下图很好的说明了分段是怎么找到实际内存地址的。

请添加图片描述

你可能发现了,虚拟地址中每个段的起始地址都是固定的,每个段的总大小也是固定的,其大小为 2 p 2^p 2p 字节 其中 p p p 为段内地址的位数。此外,栈是反向增长的,因此段表中必须维护一个比特位,描述是否为栈段。

分段的优点

**1、**生成了虚拟内存,避免了程序直接访问物理内存

**2、**很大程度上避免了内存浪费

**3、**可以很好的支持共享

随着分段机制的不断改进,系统设计人员很快意识到,通过再多一点的硬件支持,就能实现新的效率提升。具体来说,要节省内存,有时候在地址空间之间共享(share)某些内存段是有用的。尤其是,代码共享很常见,今天的系统仍然在使用。

为了支持共享,需要一些额外的硬件支持,这就是保护位(protection bit)。基本为每个段增加了几个位,标识程序是否能够读写该段,或执行其中的代码。通过将代码段标记为只读,同样的代码可以被多个进程共享,而不用担心破坏隔离。

**4、**虚拟地址翻译太慢

我们每次翻译一个虚拟地址都需要去找寻段表中的段表项,相当于多一次地址访问,这太慢了!解决方案是为计算机设置一个小型的硬件设备,将虚拟地址直接映射到物理地址,而不必再访问段表。这种设备称为转换检测缓冲区 (Translation Lookaside Buffer,TLB),有时又称为快表。快表是一个小的高速缓存,现代操作系统无论是分段还是分页中都利用了这种软件技术。

分段的缺点

**1、**太多的外部碎片

例如4kb的空间装入3kb的段,产生的1kb的空间无法在装入任何段,产生碎片的主要原因是因为分段使用的大小是不确定的。外部碎片可通过紧凑的方式以合成较大的空闲空间,但这需要大量成本,操作系统难以维护。由于这个原因分页思想诞生

分页式管理的思想

分段式管理一段时间后主存上会遍布着大大小小的外部碎片,操作系统难以维护,分页的思想就是将空间划分成较小的,固定长度的分片,这就是分页式管理,分页式管理将程序资源划分为固定大小的页,将每一个虚拟页映射到物理页之中,由于每个页是固定大小的,操作系统可以整齐的分配物理内存空间,避免产生了外部碎片,例如一个页大小是4kb,而主存是40kb,操作系统稍加管理便能确保无论何时都能整齐的装入10个页面。

页在物理内存中也不是连续存在的,进程未使用的页也没有必要为其分配内存,通过这种方式我们就解决了由分段产生的大量外部碎片问题,同时由于页比较小,只有在已使用的页才会产生较少的内部碎片,这是可以接受的,目前来看,分页是一种很好的办法。

请添加图片描述

分页地址的转换

分页地址的转换与分段地址转换一致,为页基址+页内偏移,页表是操作系统维护的,操作系统知道页表的起始位置,页表项大小是固定的,在32位地址空间中通常是8字节,这64bit中不仅存储了页基址,还存放着一些其他重要的数据。

假设我们有一个线性地址,已经经过了分段机制的转换,其地址为二进制表示0000000011_0100000000_000000000000,那他的转换过程就如下图所示

请添加图片描述

高 10 位负责在页目录表中找到一个页目录项,这个页目录项的值加上中间 10 位拼接后的地址去页表中去寻找一个页表项,这个页表项的值,再加上后 12 位偏移地址,就是最终的物理地址。

现在我们是不是出现了很多关于地址的名词,逻辑地址,线性地址,物理地址,虚拟地址,这我们就不得不讲讲Intel管理内存的两板斧了,分段与分页,对就是上面说的,进入保护模式后,分段就必须打开了,分页不是必须的,

分段机制的目的是为每个程序或者任务提供单独的代码段数据段和栈段,使其不会相互干扰。

分页机制的目的使程序可以按需取用内存,也可以在多任务的时候起到隔离内存空间的作用

逻辑地址:我们程序员写代码时给出的地址叫逻辑地址,其中包含段选择子和偏移地址两部分。

线性地址:通过分段机制,将逻辑地址转换后的地址,叫做线性地址。而这个线性地址是有个范围的,这个范围就叫做线性地址空间,32 位模式下,线性地址空间就是 4G。

物理地址:就是真正在内存中的地址,它也是有范围的,叫做物理地址空间。那这个范围的大小,就取决于你的内存有多大了。

虚拟地址:如果没有开启分页机制,那么线性地址就和物理地址是一一对应的,可以理解为相等。如果开启了分页机制,那么线性地址将被视为虚拟地址,这个虚拟地址将会通过分页机制的转换,最终转换成物理地址。

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

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

相关文章

设计模式-值类型与引用类型、深拷贝与浅拷贝、原型模式详解

一. 值类型和引用类型 1. 前言 (1). 分类 值类型包括:布尔类型、浮点类型(float、double、decimal、byte)、字符类型(char)、整型(int、long、short等)、枚举(entum)、结构体(struct)。 引用类型:数组、字符串(string)、类、接口…

DamiCMS SQL注入分析

2023年将会持续于B站、CSDN等各大平台更新,可加入粉丝群与博主交流:838681355,为了老板大G共同努力。 一、入口文件(单入口文件模式) 看一下Index.php文件代码:引入了php_safe.php文件 查看一下php_safe.php防御文件: 对变量e…

2019_41 考研408

2019年(单链表)41.(13分)设线性表采用带头结点的单链表保存,链表中的结点定义如下:typedef struct node {int data;struct node* next;}NODE;请设计一个空间复杂度为O(1)且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表L(q,a,,a,an…

【正则表达式】获取html代码文本内所有<script>标签内容

文章目录一. 背景二. 思路与过程1. 正则表达式中需要限定<script>开头与结尾2. 增加标签格式的限定3. 不限制<script>首尾的内部内容4. 中间的内容不能出现闭合的情况三. 结果与代码四. 正则辅助工具一. 背景 之前要对学生提交的html代码进行检查&#xff0c;在获…

牛客小白月赛66

牛客小白月赛66_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com)冒着期末挂科的风险打了打&#xff0c;缓解了一下网瘾&#xff0c;感觉还行最近为了期末鸽了很多期的div3&#xff0c;一学期末就手痒想训&#xff0c;感觉再不打人要没了&#xff0c;结果…

linux性能优化-内存回收

linux文件页、脏页、匿名页 缓存和缓冲区&#xff0c;就属于可回收内存。它们在内存管理中&#xff0c;通常被叫做文件页&#xff08;File-backed Page&#xff09;。通过内存映射获取的文件映射页&#xff0c;也是一种常见的文件页。它也可以被释放掉&#xff0c;下次再访问的…

DOM编程-显示网页时钟

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>显示网页时钟</title> </head> <body bgcolor"antiquewhite"> <script type"text/javascrip…

剑指offer(中等)

目录 二维数组中的查找 重建二叉树 矩阵中的路径 剪绳子 剪绳子② 数值的整数次方 表示数值的字符串 树的子结构 栈的压入、弹出序列 从上到下打印二叉树① 从上到下打印二叉树③ 二叉搜索树的后序遍历序列 二叉树中和为某一值的路径 复杂链表的复制 二叉搜索树与…

C++复习笔记8

泛型编程&#xff1a;编写的是与类型无关的通用代码&#xff0c;是代码复用的一种手段&#xff0c;模板是泛型编程的基础。 1.函数模板&#xff1a;类型参数化&#xff0c;增加代码复用性。例如对于swap函数&#xff0c;不同类型之间进行交换都需要进行重载&#xff0c;但是函数…

K_A12_003 基于STM32等单片机采集光敏二极管模块参数 串口与OLED0.96双显示

K_A12_003 基于STM32等单片机采集光敏二极管模块参数 串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明IIC地址/采集通道选择/时序对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RC光敏二极管模块1.2、STM32F103C8T6光敏二极管模块五、基础知识…

面向 3DoF+的虚拟视图合成算法研究(陈 莹)

面向 3DoF的虚拟视图合成算法研究&#xff08;陈 莹&#xff09;论文贡献多视点联合的虚拟视图合成算法视图合成中多视点伪影消除算法面向虚拟视图合成算法的 3DoF系统基于深度的虚拟视图合成算法视点映射&#xff08;3D-Warping&#xff09;三维空间映射变换&#xff08;3D-Wa…

TYPE-C 手机/电脑同时充电直播 视频采集卡方案

Type-C音视频采集卡有什么作用&#xff1f; ​能够帮助专业用户和游戏玩家迅速搭建简单、高性价比的音视频解决方案。可将新闻联播、体育竞赛、视频教学课程、网络视频等&#xff0c;通过HDMI高清视频信号分段或整体录制在本地计算机共享使用。支持多种带HDMI接口的游戏机设备…

生物素-琥珀酰亚胺酯Biotin-NHS;CAS号:35013-72-0;可对溶液中的抗体,蛋白质和任何其他含伯胺的大分子进行简单有效的生物素标记。

结构式&#xff1a; ​ 生物素-琥珀酰亚胺酯Biotin NHS CAS号&#xff1a;35013-72-0 英文名称&#xff1a;Biotin-NHS 中文名称&#xff1a;D-生物素 N-羟基琥珀酰亚胺酯&#xff1b;生物素&#xff0d;琥珀酰亚胺酯 CAS号&#xff1a;35013-72-0 密度&#xff1a;1.50.1 …

vue项目第二天

项目中使用element-ui库中文网https://element.eleme.cn/#/zh-CN安装命令npm install element-ui安装按需加载babel插件npm install babel-plugin-component -Dnpm i //可以通过npm i 的指令让配置刷新重新配置一下项目中使用element-ui组件抽离文件中按需使用element ui &…

sqoop 数据同步方案理解+问题解决

sqoop数据同步——问题与解决方案 1、sqoop导出oracle数据&#xff0c;数据源无法选择表空间&#xff0c;只能指定默认表空间的表。 方案&#xff1a;不指定数据源的表名&#xff0c;而是使用–query&#xff0c;利用sql语句把数据带出来。 例&#xff1a;--query "SELE…

【游戏逆向】内存构造发包结构体实现协议发送简单代码

捕捉到游戏的封包以后 我们可以对其进行发送来实现功能 基本有两种方式 第一种直接调用明文发包函数 第二种构造明文封包以后&#xff0c;再调用加密算法&#xff0c;然后通过send等发包函数对其进行发送 如果能够把加密算法分析透彻的话&#xff0c;第二种方式是最好的 …

element Ui树状图控件 spring boot Vue 实现角色授权功能

目录 前言&#xff1a; 二. element ui 2.1官网提供的核心代码 三.表结构 ​编辑 四.后端 4.1功能分析 4.2实体类 4.3 查询全部权限显示的结果 4.2修改角色权限的后台方法 五.vue 5.0代码总览 5.1树形图 5.2所需要的绑定数据 5.3所需方法 前言&#xff1a; 先上图…

微搭低代码从入门到精通04-创建自定义应用

微搭中的应用分为两类&#xff0c;模型应用和自定义应用。上一篇我们介绍了模型应用的创建方法&#xff0c;本篇我们介绍一下自定义应用的创建方法。 登录微搭的控制台&#xff0c;在左侧的菜单里点击应用&#xff0c;点击新建应用&#xff0c;选择新建自定义应用 输入应用的名…

logstash毫秒时间戳转日期以及使用业务日志时间戳替换原始@timestamp

文章目录问题解决方式参考问题 在使用Kibana观察日志排查问题时发现存在很多组的timestamp 数据一样&#xff0c;如下所示 详细观察内部数据发现其中日志数据有一个timestamp字段保存的是业务日志的毫秒级时间戳&#xff0c;经过和timestamp数据对比发现二者的时间不匹配。经…

1630_GNU的二进制分析工具nm简单使用探索

全部学习汇总&#xff1a; GreyZhang/toolbox: 常用的工具使用查询&#xff0c;非教程&#xff0c;仅作为自我参考&#xff01; (github.com) GNU有一套二进制的分析工具&#xff0c;之前是用过objdump的&#xff0c;但是也没有系统掌握。如果做底层软件的设计&#xff0c;这些…