IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【哈工大李治军操作系统听课笔记】L20 内存的使用与分段 -> 正文阅读

[C++知识库]【哈工大李治军操作系统听课笔记】L20 内存的使用与分段

1.取址,执行带来的问题

用一个实际的例子来引出问题,现在有一个程序在编译成指令序列后存储在磁盘上,接下来这段程序从磁盘读入到内存中,设置PC指针开始执行程序,其第一个指令为”Call 40”。这条指令会执行PC=40,即让PC指针去地址为40处读取下一条指令。这个例子里下一条指令为”MOV 1,[300]”。
在这里插入图片描述

要使得这个程序运行正确,那么”MOV 1,[300]”这条指令就必须放在地址为40的地方。那么也就意味着这个程序的起始地址必须是物理内存0处。但是我们知道物理内存0处存放的是操作系统。就算没有操作系统存放在那里,如果并发执行两个同样的程序,我们不可能将两个程序都放在物理地址0处。 这就出现了问题。

2.程序重定位

实际上一个程序在编译成为可执行程序的时候,用到的都是从0开始的相对地址。如”Call 40”中的40实际上是一个逻辑地址而非真实的地址。一个程序在载入到内存中后,操作系统会给其安排任意一段物理内存插入,例如之前的例子中的程序就可以被插入在物理内存1000的地方。此时就需要进行程序重定位(program relocation),记录程序被插入在内存中的起始地址,然后将逻辑地址40+起始地址1000得到指令的真实地址,在这里是1040。

在这里插入图片描述
3.程序重定位的时机

目前的主流操作系统重定位发生的时机都是在运行时,准确地说实在执行这条指令时才会将逻辑地址变为物理地址。

之所以不放在编译的时候,是因为程序在编译时无法预知自己将被载入到的内存位置。
而不放在载入内存的时候进行重定位是因为进程可能会因为长时间阻塞而被系统暂时换出到磁盘上以释放内存空间。等过段时间进程可以执行了再找到内存空闲的地方换入。因此进程在子载入到内存的时候仍然有可能在内存移动,不能在载入时就重定位。

在这里插入图片描述

由于只有在程序运行到当前指令时才会进行重定位,为了提高指令执行效率,我们设置了一个用于翻译地址的硬件,即存储管理部件(MMU)。MMU中有一个寄存器用于保存进程的起始地址。在运行到该指令的时候就会将指令中的逻辑地址和起始地址相加得出真正的物理地址,这个过程被称为地址转换。

但是由于MMU寄存器只有一个,在多进程视图下不可能保存多个进程的起始地址。实际上进程的起始地址保存在其对应的进程PCB中。在执行进程1的操作时,操作系统会将进程1的PCB中保存的基址赋给MMU的寄存器。这样,只要PCB中的基址信息正确,不管进程移动到内存中的哪个位置,进程切换机制都会让进程中的指令正确执行。

在这里插入图片描述

之前说过,进程切换分为两部分,指令流切换以及地址空间切换。指令流切换就是指操作系统根据PCB进程内核栈切换,用户栈切换,PC指针切换等等,而地址空间切换就是指这里的MMU寄存器切换。

4.分段的概念

我们知道一个程序实际上是由若干段组成的,例如数据段,代码段,栈段等等。因此实际上一个程序的结构应该如下:

在这里插入图片描述

因此程序要被载入内存时,应该是多个段分别载入内存之中**(注意,各个段不用相邻,有可能一个段在内存2000位置,另一个在内存4000位置)**。如果整个程序载入内存,需要记录一个基址,而现在将多个段分别载入内存,就需要记录每个段的基址,这多个基址会形成一个表,这就是著名的段表。
在这里插入图片描述

因此操作系统在遇到带有逻辑地址的指令的时候,会首先找到当前指令的段号信息,通过查找段表确定段基址,最后计算出实际地址。
在这里插入图片描述

真正的指令是段号+段内偏移构成,如图中的mov[es:bx],ax。es就是段号,bx就是段内偏移。

在这里插入图片描述

在操作系统这个进程中,段表被称为GDT表,而在一般的进程中,段表被称为LDT表。这个表存储在进程对应的PCB中。

那么内存分段的完整故事就是:一个程序在被装入内存的过程中,首先是这个程序的不同的段分别在内存中找到一块空闲的空间,把这些空闲的地方的基址分别写到LDT表中。等到LDT表初始化完成后,LDT表就会被复制到该进程对应的PCB中。这下一个程序就真正载入到内存中,可以进行取址执行了。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-27 17:12:03  更:2022-05-27 17:13:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/14 3:58:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码