清华大学《操作系统》(六):非连续内存分配 段式、页式、段页式存储管理

背景

连续内存分配给内存分配带来了很多不便,可能所有空闲片区大小都无法满足需求大小,这个分配就会失败。基于这种现状,就有了非连续内存分配的需求。非连续分配成功的几率更高,但也面对更多的问题,比如分配时是不是1个字节的空间也可以进行分配?显然1个字节为单位分配太短了。因此我们需要选择不同尺度的基本块进行分配管理。实际操作系统中出现了两种基本块,一种是段式,一种是页式。段式分的块比较大,页式分配的块比较小。分配的块越小,逻辑地址与物理地址之间的映射关系就越复杂。根据这种映射关系形成了页表。还有一种结合的方式段页式管理。

连续分配的缺点

  • 分配给程序的物理内存必须连续
  • 存在外碎片和内碎片
  • 内存分配的动态修改困难
  • 内存利用率较低

非连续分配的设计目标

针对连续内存分配的这些缺点,非连续分配的设计目标就显而易见了:提高内存利用效率和管理灵活性。具体来说有以下几条:

  • 允许一个程序使用非连续的物理地址空间;
  • 允许共享代码与数据,因为各个进程可能有很多代码是相同的或者使用的数据是相同的,比如使用了同一个函数库;
  • 支持动态加载和动态链接。

非连续分配需要解决的问题:

虚拟地址到物理地址的转换。当进程的内存地址连续时,只要知道进程内存起头的位置,就知道整个内存区域的位置了。而非连续分配则不然,逻辑地址中不同位置可能存储于物理内存中不同的区域,因此转换会比较复杂。具体的转换方式有两种:

  • 软件实现,灵活但开销大,就比如数据的外排序时,需要分几部分将数据排序存到外存,最后再整体排序;
  • 硬件实现,够用并且开销小。

非连续分配的硬件辅助机制:

非连续分配中如何选择非连续分配的内存分块大小是个很重要的问题。实际操作中主要有两种方式:

  • 段式存储管理,内存基本块较大;
  • 页式存储管理,内存基本块较小。

段式存储管理

段式存储管理中,将程序的逻辑地址空间内容分为不同的段进行管理,逻辑地址空间与物理地址空间之间的映射关系图可以如下所示:每个段内部是连续的,但是不同的段在物理内存上是不连续的。

段的概念:

  • 段表示访问方式和存储数据等属性相同的一段地址空间;
  • 一个段对应一个连续的内存块;
  • 若干个段共同组成进程的逻辑地址空间。

段访问:

逻辑地址由二元组(s,addr)表示。其中 s 表示段号,addr 表示段内偏移量。如下图:

硬件实现:

如下图所示:在程序P运行过程中,CPU要访问逻辑地址中的某个位置,已经知道段号与偏移。操作系统中维护段表,段表记录段号对应的基址与长度,首先MMU比对偏移量与段号对应的长度,如果偏移量大于长度说明操作不合法内存异常,否则是合法的,此时将段基址与偏移相加得到真实物理地址,然后进行访问。

页式存储管理

页式存储管理中,物理内存被划分为大小相同的基本分配单位,我们称为页帧,页帧的大小必须是2的幂次方,这样进行地址转换的时候比较快,可以通过二进制移位实现。比如32位系统中,4Kbyte是常见的页帧大小。而逻辑内存也被划分为大小相同的基本分配单位,我们称为页面,页面与页帧大小必须相等。页帧与页面一个是对物理内存地址一个是对逻辑内存地址而言的。因此页式存储管理中要处理逻辑地址与物理地址的转换,也就变为对页面到页帧的转换。而储存映射关系的表我们称为页表,由操作系统维护。具体硬件实现则是由MMU和TLB共同实现。

物理内存被分为大小相等的帧,物理内存的地址用一个(f,o)二元组表示,其中 f 是帧号,比如一个帧号由 f bit表示,那也就是说一共有 2**f 个帧,o 是帧内偏移,比如偏移由 S bit 表示,那么一个帧内 2**S 有字节。那么 物理地址 =f*2^S+o 。

逻辑内存被划分为大小相等的页,表示方式与帧类似。由于帧与页的大小是相等的。因此在映射关系中 ,页内偏移与帧内偏移是相等的,但是页号与帧号通常是不相等的。因为逻辑内存是连续的,物理地址不是连续的。

页表

那么如何实现页与帧之间的地址转换呢?也就是如何实现逻辑地址与物理地址之间的转换。如下图:操作系统维护页表,页表内存储页号与帧号之间的映射关系。页表基址表明了页表存储在什么地方。比如当程序P执行过程中,CPU要访问(p, o),操作系统通过页表得到帧号f,通过(f, o)找到物理内存地址。而由于帧和页的大小是2的幂次方,因此实际上地址就是将 f 左移 S 位之后加上 o 即得到物理地址。

上面简单介绍了页表的作用,而实际上页表中还有一些其他辅助的内容。下面我们对页表进行详细讨论。每个进程都有一个页表,且有以下特点:

  • 每个页面对应一个页表项
  • 页表随进程运行状态而动态变化
  • 页表的起始地址即基址存储在页表基址寄存器(PTBR: Page Table Base Register)中

页表内除了存储前面提过的帧号,还存储了一些页表项标志位:

  • 存在位,记录该页号是否有对应的帧;
  • 修改位,记录页面的内容是否修改了;
  • 引用位,记录是否有对该页面的引用。

那么实际操作中,如下图,标志位为0意味着没有给页分配帧,就可以动态的进行变化。

页式访问的性能问题

内存访问的性能问题:访问一个物理内存单元需要两次访问内存。第一次先访问页表进行查询,第二次才是访问物理内存获取数据。
页表的大小问题:页表可能非常大。比如一个64位机器(2**64 字节内存),假如一页大小为1024字节(2**10),那么一共可以产生页(2**54 帧),64位的系统想要表示一个帧的地址就需要64位,也就是8字节,也就是说想表示一个帧,即使不考虑标志位也需要8字节,那使用很多页面,比如全部使用 2**54 页,就需要 2**57 字节,仅仅存储页表就要这么多字节占用了很多空间。

针对这些问题,也有一些对应的解决方案:

  • 缓存:程序执行时具有连续性即相邻性,访问了一个数组第一个元素,下一个极有可能访问第二个元素,因此当我缓存下来页表项,利用缓存可以极大可能地访问到想要的数据。
  • 间接访问:将长页表切断,实际就是多级页表,一层层去查询。

为了缓解上述性能问题,出现了一些解决方案,比如快表、多级页表和反置页表,下面对这几种解决方案进行详细讨论。

快表(TLB: Translation Look-aside Buffer):

快表是指缓存近期访问过的页表项。它有以下特点:

  • TLB使用关联存储(associative memory)实现,具备快速访问性能,因为关联存储在CPU内;
  • 如果TLB命中,可以直接访问物理内存;
  • 如果TLB未命中,仍需查询页表,并将对应表项更新到TLB中。

如果能够很大比例地命中,就可以大幅度提高访问效率。

多级页表

多级页表顾名思义,类似于树的概念,一级一级往下查询,图示如下:比如图中是三级页表,逻辑地址的表示由四元组 表示。p1、p2、p3 分别表示在各级页表中的偏移,o 则表示物理内存中的偏移。通过多级页表可以有效减少每级页表的长度。

具体操作中,比二级页表的操作如下:一级页表的起始地址存储在CPU寄存器CR3中,然后一级一级根据偏移获取实际内存地址。

反置页表页寄存器

反置页表也是为了减少页表占用存储空间的一种做法。对于大地址空间系统,比如64位系统,多级页表变的非常繁琐,比如5级页表,正常情况下总共需要6次查询。并且逻辑地址空间的增长速度快于物理地址空间。每个进程有一个页表,随进程数量增加页表占用的存储空间也会增加。

针对上述情况,出现了页寄存器,页寄存器与反置页表思路相同:

  • 不让页表与逻辑地址空间的大小相对应;
  • 让页表与物理地址空间的大小相对应。

通过这个思路就可以使页表占用空间与进程数目没有关系,而至于物理内存的大小有关。接下来我们首先对页寄存器进行介绍,理解了页寄存器就可以轻松理解反置页表。页寄存器将每个物理帧与与一个页寄存器关联,寄存器内存储以下内容:

  • 使用位:此帧是否被进程占用;
  • 占用页号:对应的逻辑页号 p ;
  • 保护位:比如可读、可写等性质。

由上面的内容我们可以看到页寄存器的优点是与逻辑地址空间大小无关,并且大小相对物理内存而言很小。缺点是需要在页寄存器中存储页号,也就是帧号是键,页号是帧,而进程运行时CPU产生的是逻辑地址页号,因此需要在页寄存器中搜索逻辑地址的页号。那么这种搜索是比较困难的。实际操作中,采用hash将页号映射到帧号,提高检索效率。这样又产生一个问题就是hash冲突,出现冲突时遍历冲突链表,找到需要的帧号。同时还可以将快表的思想融入进来,缓存使用过的页号帧号映射。引入快表又引入了新的问题,快表存储在CPU缓存中容量被限制到很小,同时快表的功耗是很大的。

反置页表

接下来我们看下反置页表。反置页表也是基于hash映射查找页对应的帧,但是反置页表将进程号也考虑进来,对进程号和页号同时进行hash。这里我自己的理解是最初给进程分配帧的时候就是根据哈希值进行分配的,因此查找时自然可以根据哈希值进行查询。冲突解决方式依然是链表的方式解决,查询发现第一个地址内的进程号与页号与需要的进程号与页号不一致时则继续查询链表中的下一个节点。过程如下图:哈希值加反置页表基址得到反置页表中的位置,验证进程号和页号,命中则根据hash结果查询物理内存。

具体实现看下图。pid和vpn(virtual page number)共同参与哈希,得到一个物理地址,根据这个地址去查询反置页表,验证pid和vpn是否匹配,不匹配则查询next中存储的地址,此时匹配,则访问此时对应的物理地址。

段页式存储管理

段页式存储管理是将前面讲过的段式存储管理与页式存储管理结合起来。这一节对段页式存储管理进行讨论。

段页式存储管理的需求

  • 段式存储管理在内存保护方面有优势。如何理解呢?因为分段时是将具有相同访问方式和数据属性的内容分配到一段连续内存中,也就是每个段内的数据属性是相似的,便于统一管理和保护。
  • 页式存储管理在内存利用和优化转移到后备存储方面有优势。因为页式存储管理中内存划分的基本块更小,对提高内存的利用率有很大帮助。同时对于内外存之间转移也是比较快和利用率高的。

段页式存储管理的实现

段页式存储管理的实现如下图。逻辑地址由段号+页号+业内偏移组成。首先根据寄存器得到段表基址段表基址加段内偏移得到段表项,段表项内存储页表基址页表基址加页偏移得到帧号,帧号加页内偏移得到实际物理内存地址

段页式存储管理的优势

段页式存储管理将段式存储管理和也是存储管理的优势结合在了一起。最明显的一个是可以非常方便地实现进程间的段共享。如下图,只要两个进程中共享段指向相同的页表基址,就可以实现内存共享。

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

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

相关文章

C语言第三次博客作业---单层循环结构

一、PTA实验作业。 题目1 1.实验代码 int n,i; double height1,height2;//1为输入身高&#xff0c;2为输出身高。 char sex; //1<height1<3; //N<1; scanf("%d",&n); while(n--){getchar();scanf("%c%lf",&sex,&height1);switch(sex)…

清华大学《操作系统》(七):虚拟存储、覆盖、交换

接下来几节都是对虚拟存储的讲解。虚拟存储是非连续存储管理的扩展。通过将内存中的数据暂存到外存的方式&#xff0c;为进程提供更大的内存空间。虚拟存储出现的主要原因是因为程序规模的增长速度远远大于存储器容量的增长速度&#xff0c;导致内存空间不够用。其实针对内存空…

遵义大数据中心项目工程概况_市委书记张新文到曹州云都大数据中心等项目现场调研建设情况...

4月25日&#xff0c;市委书记张新文到曹县调研重点项目建设情况&#xff0c;研究推进措施。市委常委、秘书长任仲义参加活动。张新文首先来到曹州云都大数据中心项目建设现场&#xff0c;查看项目推进情况。曹州云都大数据中心&#xff0c;是涵盖云计算区、研发办公区、公寓生活…

linux 可执行文件的分析(gcc GUN BUILEIN)

1、GCC The History of GCC 1984年&#xff0c;Richard Stallman发起了自由软件运动&#xff0c;GNU (Gnus Not Unix)项目应运而生&#xff0c;3年后&#xff0c;最初版的GCC横空出世&#xff0c;成为第一款可移植、可优化、支持ANSI C的开源C编译器。GCC最初的全名是GNU C Com…

Cassandra 的数据存储结构——本质是SortedMapRowKey, SortedMapColumnKey, ColumnValue

Cassandra 的数据存储结构 Cassandra 的数据模型是基于列族&#xff08;Column Family&#xff09;的四维或五维模型。它借鉴了 Amazon 的 Dynamo 和 Googles BigTable 的数据结构和功能特点&#xff0c;采用 Memtable 和 SSTable 的方式进行存储。在 Cassandra 写入数据之前&a…

清华大学《操作系统》(八):置换算法

功能&#xff1a;置换算法是指当出现缺页异常时&#xff0c;需要调入新页面而内存已满时&#xff0c;置换算法选择被置换的物理页面。 设计目标&#xff1a; 尽可能减少页面的调入调出次数&#xff1b;把未来不再访问或短期内不访问的页面调出。 页面锁定&#xff1a; 了解具…

烂泥:通过vsphere给esxi添加本地硬盘

公司ESXi服务器的硬盘空间不够使用&#xff0c;现在新加了一块硬盘在ESxi服务器上。在服务器上添加完硬盘后&#xff0c;在Vsphere上是看不到新加硬盘的。 下面我们来通过虚拟机模拟该情况&#xff0c;先添加一块硬盘。如下图&#xff1a; 在Esxi添加完硬盘后&#xff0c;现在通…

清华大学《操作系统》(九):进程和线程

进程 定义&#xff1a; 进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行的过程。 组成&#xff1a; 代码数据状态寄存器&#xff08;正在运行的一个程序的所有状态信息&#xff09;&#xff1a;CPU状态CP0、指令指针IP通用寄存器&#xff1a;AX、BX、CX…

开始Flask项目

1.新建Flask项目。2.设置调试模式。3.理解Flask项目主程序。4.使用装饰器&#xff0c;设置路径与函数之间的关系。5.使用Flask中render_template&#xff0c;用不同的路径&#xff0c;返回首页、登录员、注册页。6.用视图函数反转得到URL&#xff0c;{{url_for(‘login’)}}&am…

烂泥:mysql数据库使用的基本命令

1、连接数据库的格式 mysql -h IP -u用户名 -p密码; 1.1连接远程数据库 mysql -h 192.168.1.214 -uroot -p123456 也可写成&#xff1a; mysql -h 192.168.1.214 -u root -p 123456 1.2连接本地数据库 mysql -uroot -p123456 也可写成&#xff1a; mysql -u root -p 123456 2、…

《操作系统》OS学习(十):进程控制

进程切换&#xff08;上下文切换&#xff09;&#xff1a; 定义&#xff1a;暂停当前运行进程&#xff0c;从运行状态变成其他状态&#xff0c;调度另一个进程从就绪状态变成运行状态要求&#xff1a;切换前&#xff0c;保存进程上下文&#xff1b;切换后&#xff0c;恢复进程…

GCC 命令选项使用详解

GCC 命令行详解[转帖] 1、gcc包含的c/c编译器 gcc、cc、c、g gcc和cc是一样的&#xff0c;c和g是一样的&#xff0c;一般c程序就用gcc编译&#xff0c;c程序就用g编译 2、gcc的基本用法 gcc test.c这样将编译出一个名为a.out的程序 gcc test.c -o test这样将编译出一个名为t…

mvn 打包_Spark源码打包编译的过程

前言上篇文章介绍了下 安装sbt环境 启动scala项目安装SBT环境运行Scala项目为什么要弄这个 因为我本来是想对spark源码编译部署spark是用scala语言编译的spark源码https://gitee.com/pingfanrenbiji/sparkspark提供的编译方式编译的前提是将所有的依赖包都下载下来而资源包管理…

清华大学《操作系统》(十一):处理机调度

一、处理机调度概念 进程切换&#xff08;上下文切换&#xff09;&#xff1a;切换CPU的当前任务&#xff0c;从一个进程/线程到另一个&#xff0c;保存当前在PCB/TCB中的执行上下文&#xff0c;读取下一个的上下文 CPU调度&#xff1a;从就绪队列中挑选一个进程/线程作为CPU…

对称加密与非对称加密

&#xff08;一&#xff09;对称加密&#xff08;Symmetric Cryptography&#xff09; 对称加密是最快速、最简单的一种加密方式&#xff0c;加密&#xff08;encryption&#xff09;与解密&#xff08;decryption&#xff09;用的是同样的密钥&#xff08;secret key&#xff…

清华大学《操作系统》(十二):临界区与锁

多进程并发运行&#xff0c;导致多个进程间有资源共享&#xff0c;比如CPU、内存&#xff0c;因此存在不确定性和不可重现&#xff0c;可能导致多次运行结果不一致。因此操作系统需要利用同步机制在并发执行的同时&#xff0c;保证一些操作是原子操作。 互斥是指一个进程占用了…

清华大学《操作系统》(十八):管程于信号量

信号量与管程也是进程间通信的方式。信号量是与锁在同一层级实现的&#xff0c;是操作系统提供的一种协调共享资源访问的方法。信号量由操作系统管理&#xff0c;操作系统作为管理者地位是高于进程的。 一、信号量 1、信号量&#xff08;semaphore&#xff09;&#xff1a;是操…

Iptalbes自动封杀暴力破解(Qmail邮件系统)者的IP地址

今天发现Qmail邮件系统的maillog里面有大量的“user not found”信息&#xff0c;通过下面的日志不难发现&#xff0c;是来自同一IP的很多不同的用户连接Qmail邮件系统认证失败的信息。黑客试图通过这种方式来破解Qmail邮件系统的用户名和密码&#xff0c;从而来发送大量的垃圾…

安装Postman

在web和移动端开发时&#xff0c;常常会调用服务器端的restful接口进行数据请求&#xff0c;为了调试&#xff0c;一般会先用工具进行测试&#xff0c;通过测试后才开始在开发中使用。 这里介绍一下如何在chrome浏览器利用postman应用进行restful api接口请求测试。 因为&#…

清华大学《操作系统》(二十):死锁和进程通信

一、死锁 死锁&#xff1a;一组阻塞的进程&#xff08;两个或多个&#xff09;&#xff0c;持有一种资源&#xff0c;等待获取另一个进程所占有的资源&#xff0c;而导致谁都无法执行。 可重复使用的资源&#xff1a; 在一个时间只能一个进程使用&#xff0c;且不能被删除。…