分段

基本方法

分段就是基于用户视图的内存管理方案。逻辑地址空间是由一组段构成的,每个段都有名称和长度。地址指定了段名称和段内偏移。因此用户通过两个量来指定地址:段名称段偏移
为了简单,进行对段的编号,是通过段号而不是段名称来引用的,所以逻辑地址由有序对组成:<段号,偏移>。

分段硬件

用户是通过二位地址来引用程序内的对象的,但是实际物理内存仍然是一维的字节序列。所以我们需要定义一个实现方式,用来映射用户定义的二维地址到一维的物理地址。这个地址是通过段表来实现的。段表的每个条目都有段基地址和段界限。段基地址包含该段在内存中的开始物理地址,段界限指定该段的长度。

段表的使用如上图所示,每个逻辑地址由两部分组成:段号s和段偏移d。段号用作段表的索引,逻辑地址的偏移d应位于0和段界限之间。如果不是这样,那么会陷入操作系统中(逻辑地址试图访问段的外面);如果d合法,那么就与基地址相加而得到所需字节的物理内存地址。因此,段表实际上是基址寄存器值和界限寄存器值的对的数组。

分页

分段允许进程德尔物理地址空间是非连续的。分页是提供这种优势的另一种内存管理方案,使用分页可以避免外部碎片和紧缩。

基本方法

实现分页的基本方法涉及将物理内存分为固定大小的块,称为页帧;而将逻辑内存也分为同样大小的块,称为页面。当执行一个进程时,它的页从文件系统或备份存储等源处,加载到内存的可用帧。备份存储划分为固定大小的块,它与单个内存帧或与多个内存帧(簇)的大小一样。
分页的硬件如下图所示,由CPU生成的每个地址分为两部分:页码§和页偏移(d)。页码作为页表的索引。页表包含每页所在的物理内存的基地址。这个基地址和页偏移的组合就是物理内存的内存地址,可发送到物理单元。

页大小是由硬件决定的。页的大小为2的幂,如果逻辑地址空间为2m2^m2m,且页大小为2n2^n2n字节,那么逻辑地址的高m-n位表示页码,而低n位表示页偏移。

其中p为页表的索引,d为页的偏移。

采用分页方案不会产生外部碎片:每个空闲帧都可以分配给需要他的进程,但是,分页有内部碎片。分页是以帧为单位进行的,如果进程所要求的内存并不是页的整数倍,那么最后一个帧就用不完。如果进程大小与页大小无关,那么每个进程的内部碎片的均值为半页。

硬件支持

页表的硬件实现有多种方法,最简单的一种方法就是:将页表作为一组专用的寄存器来实现。这些寄存器应用告诉逻辑电路来构造,以高效的进行分页地址的转换。CPU分派器在加载其他寄存器的时候,也需要加载这些寄存器。注意,这种方法适用于页表比较小的情况下。
大多数的现代计算机都允许页表非常大,对于这种情况,需要将页表放在内存中,并将页表基址寄存器指向页表。改变页表只需要改变这一寄存器就行了。注意,如果采用这种方法,访问一个字节需要两次访问内存(一次用于页表条目,一次用于字节)。
标准方法是:采用转换表缓冲区(TLB),TLB是关联的高速内存,TLB条目是由两部分组成:键(标签)和值。当关联内存根据给定值查找时,它会同时与所有的键进行比较。如果找到条目,就得到相应值的字段。
TLB和页表一起使用的方法是:TLB只包含少数的页表条目。当CPU产生一个逻辑地址后,它的页码就发送到TLB。如果找到这个页码,它的帧码就立即可用,可用基于访问内存。如果页码不在TLB中,也就是TLB未命中。那么就需要访问页表。有的TLB在每个TLB条目中还保存地址空间标识符(ASID),ASID唯一标识每个进程,并为进程提供地址空间的保护。

保护

分页情况下的内存保护是通过与每个帧关联的保护位来实现的。用一个位可以定义一个页是可读可写的还是只可读。每次内存引用都要通过页表,来查找正确的帧码。在计算物理地址的同时,可以通过检查保护位来验证与没有对只读页进行操作。
还有一个位通常与页表中的每一条目相关联:有效-无效位。当该位为有效时,该值表示相关的页在进程的逻辑地址空间内,因此是合法的页。当该位是无效的时候,该值表示先关的页不在进程的逻辑地址空间内。通过使用有效-无效位,非法地址会被捕捉到。
还有一个问题,一个进程很少会使用的它的所有地址空间,如果为地址范围内的所有页都在页表中建立一个条目,这将是非常浪费的。有的系统会提供硬件来解决这个问题,如**页表长度寄存器(PTLR)**来表示页表的大小,该寄存器的值可用于检查每个逻辑地址以验证其是否位于进程的有效范围内。

共享页
分页的优点之一就是可以共享公共代码。
注意:代码必须是可重入代码纯代码才可以共享。可重入代码是不能自我修改的代码,他在执行期间不会改变

页表结构

分层分页

现代操作系统支持大逻辑地址空间,在这种情况下页表本身可以非常的大。比如一个位逻辑地址空间的计算机操作系统。如果系统的页大小为4KB(2122^{12}212),那么页表可以多达100万的条目,假设每个条目有4字节,那么每个进程需要4MB物理地址空间来存储页表本身。
常用的解决方法就是分层分页。比如两层分页算法,就是将页表在分页。

其中p1p_1p1​是用来访问外部页表的索引,p2p_2p2​是内部页表的页偏移,这种方案一般称为向前映射页表
对于64位的架构,分层分页是不适用的,因为每一层的页表分完之后还是太大了。

哈希页表

处理大于32位地址空间的常用方法就是使用哈希页表。采用虚拟页码作为哈希值。哈希页表的每一个条目都包括一个链表,该链表的元素哈希到同一位置(该链表用来解决碰撞)。每个元素由三个字段组成:

  1. 虚拟页码
  2. 映射的帧码
  3. 指向链表内下一个元素的指针

该算法的工作:虚拟地址的虚拟页码哈希到哈希表。用虚拟页码与链表内的第一个元素的第一个字段相匹配。如果匹配,那么相应的帧码就用来形成物理地址;如果不匹配,那么与链表内的后续节点的第一个字段进行比较,以查找匹配的页码。

基于哈希页表的一个变体采用聚簇页表,哈希表中的每个条目引用多个页而不是单个页,因此单个页表条目可以映射到多个物理帧。聚簇页表对于稀疏地址空间特别有用,这里的引用是不连续的并且散步在整个地址空间中。

倒置页表

通常情况下每个进程都有一个页表,该进程使用的每个页都是该页表的一项。但是这种方法的缺点就是会造成每个页表可能包含数以百万记的条目,占用大量的内存。
所以有了倒置页表。对于每个真正的内存页或帧,倒置页表才有一个条目。每个条目包含保存在真正内存位置上的页的虚拟地址以及拥有该页进程的信息。所以在一个系统中只有一个页表,并且每物理内存的页只有一条相应的条目。
由于一倒置页表通常包含多个不同的映射物理内存的地址空间,通常要求它的每个条目保存一个地址空间标识符,用来确保具体进程的每个逻辑页可映射道德相应的物理帧。

参考:《操作系统概念》(第九版)

转载于:https://www.cnblogs.com/lishanlei/p/10707669.html

OS之内存管理 ---基本的内存管理策略(二)相关推荐

  1. C/C++内存分配与Linux内存管理进程所涉及到的五个数据段 .

    一. 在c中分为这几个存储区 1.栈 - 由编译器自动分配释放 2.堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收 3.全局区(静态区),全局变量和静态变量的存储是放在一块的, ...

  2. Java内存管理:Java内存区域 JVM运行时数据区

    Java内存管理:Java内存区域 JVM运行时数据区 在前面的一些文章了解到javac编译的大体过程.Class文件结构.以及JVM字节码指令. 下面我们详细了解Java内存区域:先说明JVM规范定 ...

  3. 自我管理数据缓冲区内存

    http://www.ibm.com/developerworks/cn/linux/wa-memmng/index.html 简介: C 程序设计语言定义了两个标准的内存管理函数:malloc() ...

  4. C语言动态内存管理和动态内存分配函数

    给变量分配内存空间可分为静态内存分配和动态内存分配. 静态内存分配属于编译时给变量分配的空间,动态分配属于在程序运行时给变量分配的空间 静态分配属于栈分配,动态分配属于堆分配 运行效率上,静态内存比动 ...

  5. Windows内存管理和linux内存管理

    windows内存管理 windows 内存管理方式主要分为:页式管理,段式管理,段页式管理. 页式管理的基本原理是将各进程的虚拟空间划分为若干个长度相等的页:页式管理把内存空间按照页的大小划分成片或 ...

  6. 属性与内存管理(属性与内存管理都是相互关联的)

    <span style="font-size:18px;"> 属性与内存管理(属性与内存管理都是相互关联的)第一部分一,属性:属性是OC2.0之后出来的新语法,用来取代 ...

  7. Oracle 内存一 手动内存管理,自动内存管理

    oracle的内存分为两个部分.一个是SGA(system global area),一个是PGA(program global area).所谓的内存管理,就是对这两部分区域进行管理.oracle的 ...

  8. 【Linux 内核 内存管理】优化内存屏障 ③ ( 编译器屏障 | 禁止 / 开启内核抢占 与 方法保护临界区 | preempt_disable 禁止内核抢占源码 | 开启内核抢占源码 )

    文章目录 一.禁止 / 开启内核抢占 与 方法保护临界区 二.编译器优化屏障 三.preempt_disable 禁止内核抢占 源码 四.preempt_enable 开启内核抢占 源码 一.禁止 / ...

  9. C语言之动态内存管理与动态内存函数

    文章目录 一.为什么存在动态内存分配? 二.动态内存函数的介绍 1.malloc和free 2.calloc函数 3.realloc函数 一.为什么存在动态内存分配? 学习动态内存的管理方法之前,我们 ...

  10. 内存管理相关【内存布局内存管理方案】

    iOS系统下的内存布局 最上面是内核区,最下面是保留区,中间是给程序加载的空间. 从高地址到低地址依次为内核区.栈.堆.静态全局区(未初始化区域.bss和已初始化区域.data).代码区.保留区: 程 ...

最新文章

  1. 7 个显著提升编码效率的IntelliJ IDEA必备插件
  2. Excel 设定密码保护特定的内容
  3. DL之DNN:自定义2层神经网络TwoLayerNet模型(封装为层级结构)利用MNIST数据集进行训练、GC对比
  4. 近似推断包括采样和变分两种方法,前者是通过_____进行近似,后者是通过_______进行近似。
  5. 控制游戏中物体的移动速度
  6. Angularjs 开始之Hello world
  7. 在win8下安装使用java及在win8下部署java环境变量-图文
  8. 如何用Sql更新默认值
  9. bnx2: Can't load firmware file bnx2/bnx2-mips-09-6.2.1b.fw
  10. 创建ServerSocket出错Permission denied
  11. pdca管理循环基本主张_PDCA管理循环图怎么画?干货分享高颜值图形图表软件
  12. 虚函数表存储的位置(解析C++内存分配及其编译分段)
  13. 2021-03-26 大数据技术对企业管理的影响和应用前景分析
  14. 淘宝自动回复机器人配置手册——目前2018年淘宝主流自动回复软件一览
  15. 嵌入式睡眠监控报警仪的研究及设计
  16. 如何扩展Linux系统分区大小
  17. 月薪30k的程序员应聘时面试官都会问什么问题
  18. npm run serve 报错:Error: error:0308010C:digital envelope routines::unsupported
  19. 详细解释基址寻址和变址寻址区别
  20. Linux高性能集群(AMD处理器)Linpack测试方法

热门文章

  1. 构造方法、类的初始化块以及类字段的初始化顺序
  2. 由SecureCRT引发的思考和学习
  3. 那些帮助你成为优秀前端工程师的讲座——《性能篇》
  4. 基本设计模式:单例模式和工厂模式代码实现
  5. 2008年5月小记(??, #, DataContractJsonSerializer, CTE Ranking top)
  6. 龟兔赛跑的升级版本和在课业学习上的应用
  7. 《守望先锋》阵亡镜头、全场最佳和亮眼表现是如何设计
  8. Python爬虫-HTMLSession的使用
  9. iOS攻防——(四)class-dump-与-Dumpdecrypted-使用
  10. MyEclipse调试过程中遇到一个奇怪的问题