分段
分页和分段的区别
来源:https://blog.csdn.net/zhongyangtony/article/details/80879425
- 目的
页是信息的物理单位,分页是为实现离散分配方式,以消减内存的外零头,提高内存的利用率。或者说,分页是出于系统管理的需要而不是用户需要。
段是信息的逻辑单位,它含有一组其意义相对完整的信息。分段的目的是为了更好地满足用户的需要。
- 长度
页的大小固定而且由系统决定,由系统把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而在系统中只能有一种大小的页面。
段的长度不固定,决定于用户所编写的程序,通常由编译程序在对程序进行编译时,根据信息的性质来划分。
- 地址空间
页的地址空间是一维的,即单一的线形地址空间,程序员只要利用一个记忆符就可以表示一个地址。
作业地址空间是二维的,程序员在标识一个地址时,既需要给出段名,又需给出段内地址。
- 碎片
分页有内部碎片无外部碎片
分段有外部碎片无内部碎片
- 绝对地址
处理器使用页号和偏移量计算绝对地址
处理器使用段号和偏移量计算绝对地址
- 管理方式
对于分页,操作系统必须为每个进程维护一个页表,以说明每个页对应的的页框。当进程运行时,它的所有页都必须在内存中,除非使用覆盖技术或虚拟技术,另外操作系统需要维护一个空闲页框列表。
对于分段,操作系统必须为每个进程维护一个段表,以说明每个段的加载地址和长度。当进程运行时,它的所有短都必须在内存中,除非使用覆盖技术或虚拟技术,另外操作系统需要维护一个内存中的空闲的空洞列表。
特别的,当使用虚拟技术是,把一页或一段写入内存时可能需要把一页或几个段写入磁盘。
- 共享和动态链接
分页不容易实现,分段容易实现
分段
在机器上提供多个互相独立的地址空间,称为段(segment)
每个段由线性地址序列构成,从0到某个最大值,每个段的长度可以是0到允许最大值之间的任意值
不同的段长度可以不同,而且通常也是不同
段的长度在运行期间可以改变,堆栈段的长度在数据也如时增长,在数据弹出时减小
在一维地址空间中,由多个动态增长的表时,一个表可能会装上另一个
由于每个段都构成了一个独立的地址空间,不同的段可以独立地增长或减小而不会影响其他的段,如果某个段中的一个堆栈需要更多的地址空间来增长,它可以做到,因为在它的地址空间中某有任何其他东西阻挡。
当然,段有可能被装满,不过段通常很大,所以这种情况发生的可能性很小。
要在这种分段的或二位的存储器中指明一个地址号,必须提供一个两段式地址:段号和段内地址。
分段内存允许每个表独立于其他表增大或减小
分段的基本原理
分段
程序划分为若干个段,每个段定义了一个组逻辑信息,可以是一张表,一个堆栈等
每个段从0编址,段长度不等
整个程序的地址空间由多个段组成,是二维的。即逻辑地址由短号和段内地址组成。
分段系统的地址结构
上例的地质结构中,允许每个段的最大长度是\(2^{16}B\)(64KB),一个程序组多允许有\(2^{16}\)(64K)个段
段表
分段:系统为每个段分配一个连续的分区,而进程中的各个段可以离散地放在内存不同的分区中
段表:记录每个段在内存的起始地址以及段长
地址变换机构
根据逻辑地址中的段号查找页表
找到该段的起始地址+段内地址,即物理地址
分页和分段的比较
理由 | 分页 | 分段 |
---|---|---|
需要程序员知道正在使用这项技术吗? | 不需要 | 需要 |
有多少个线性地址空间 | 1 | 多个 |
全部地址空间可以超过物理存储器的大小吗 | 可以 | 可以 |
例程和数据可以区分并单独保护吗 | 不能 | 能 |
能够很容易地容纳长度变化的表吗 | 不能 | 能 |
有助于在用户间共享例程吗 | 否 | 能 |
为什么发明这个技术 | 为了得到更大的线性地址空间而不用买更多的物理存储器(省钱) | 为了使得程序和数据划分到逻辑独立的地址空间,以有助于共享和保护 |
纯分段的实现
分段和分页的实现有着本质的区别:页是定长的,而段不是。
在系统运行一段时间后,内存被划分为许多块,一些包含段,一些包含空洞,这种现象被称为棋盘(checkerboarding)或者外碎片(external fragmentation)。
它在空闲区上浪费了内存,而这可以通过压缩来解决。
(a)-(d):棋盘的生长
(e):通过压缩消除棋盘
分段和分页的结合—段页式系统
基本原理
用户程序分段,每个段再分页
地址结构
数据结构
页表:每个段一张页表
段表:与纯分段不同,记录的是页表始址和页表长度
地址变换过程
- 根据逻辑地址中的段号查找段表得到页表地址
- 根据页表地址找到相应页表,根据页号查找页表,得到页框号
- 页框号+页内地址,得到物理地址
分段和分页结合:MULTICS
如果段比较大,把它整个保存在内存中可能不方便,甚至是不可能的。这导致了对它进行分页的想法,这样,只要那些实际需要的页才被载入。
MULTICS的设计者决定把每个段当作一个虚拟存储器并对他进行分页,以结合分页的优点(统一的页面尺寸以及在只是用一部分时不用把整个段全部保存在内存)和分段的优点(易于编程、模块化、保护和共享)。
MULTICS的虚拟存储器
(a):描述符段指向页表
(b):一个段描述符,其中数字为域的长度
MULTICS的地址由两部分构成:段和段内地址。段内地址由分为页号和页内地址,进行发生内存引用时,算法如下:
- 使用段号找到段描述符
- 检查该段的页表是否在内存中,如果在,定位其位置;如果不在,就发出一个缺段。如果违反了段的保护要求,发出一个错误(陷阱)
- 检查所请求虚页的页表项。如果页面不在内存中,则发出一个缺页,如果在内存中,就从页表项中提取该页在内存中的起始地址
- 把偏移地址加到页的起始地址上,得到要访问的字在内存的地址
- 最后进行读或写操作
34位的MULTICS虚拟地址
将两部分组成的MULTICS地址转换到内存地址
简化的MULTICS TLB
- 两种页面长度的存在使实际的TLB更加复杂
分段和分页的结合:Intel Pentium
Pentium在许多方面都类似于MULTICS,包括既有分段又有分页
Pentium有16K个独立的段,每个段最多可以容纳10亿个32位字。尽管段的数目较少,但是大的段容量更为重要,因为几乎没有程序需要1000个以上的段,不过有很多程序需要大的段。
Pentium虚拟存储器的核心是两张表:LDT(Local Descriptor Table,局部描述符表)和GDT(Global Descriptor Table,全局描述符表)。
为了访问某一个段,Pentium程序首先载入该段的选择符(selector)到机器中6个段寄存器中的某一个。在执行过程中,CS寄存器保存代码段的选择符,DS寄存器保存数据段的选择符。其他的段寄存器不太重要。每个选择符都是一个16位的数,如下图所示。
Pentium的选择符
当选择符载入段寄存器时,对应的描述符被从LDT或GDT中读取并存入微程序寄存器,以便快速地访问。描述符由8个字节组成,包括段基地址、长度和其他信息,如下图所示。
- Pentium的代码段描述符
- 数据段稍有不同
(selector, offset)对到线性地址的转换
每个运行程序都有一个由1024个32位项组成的页目录(page directory),其地址由一个全局寄存器指出。目录中的每个项都指向一个同样也包含1024个32位项的页表。该页表项指向页框。该方案如图所示。
线性地址到物理地址的映射
如果一个应用程序不需要分担,只需要单个分页的32位地址空间,该模型也是可能的。所有的段寄存器被设置位同一个选择符,其描述符的Base = 0,Limit设置为最大。
事实上,当前所有Pentium的操作系统都是这样工作的。OS/2是唯一使用Intel MMU体系结构的所有功能的操作系统。
总而言之,不得不称赞Pentium的设计者。提出的目标是互相冲突的:实现纯粹的分页、纯粹的分段和分页段管理,还要同时兼容286,并且有效完成所有这些,最终的设计简洁、干净,令人不可思议。
Pentium中的保护
小结
本章中我们分析了存储器管理。最简单的系统中是没有任何交换或分页的。一旦程序载入内存,它将一直在内存中运行直到结束。某些操作系统在同一时刻只允许一个进程在内存中,而其他的则支持多道程序。
接下来是交换。系统通过使用交换可以处理超过内存大小的进程。没有空间的进程会被换出到磁盘上。
内存和磁盘上的自由空间可以使用位映像、空闲区列表来记录。
许多高级计算机都有某种形式的虚拟存储器。在最简单的形式中,每一个进程的地址空间被划分为同等大小的块称为页。页可以被放入内存中任何可用的页框中。
现在有许多页面置换算法;两种比较好的算法是老化和WSClock算法。
分页系统可以通过程序中抽象的页面引用串来建模,并且在不同的算法中使用相同的引用串。这些模型可以用于对分页行为作出某些预测。
为了使分页系统很好地工作,选择一个算法是不够的;需要注意个的问题是:决定工作集、内存分配策略以及页面尺寸。
分段有助于处理运行期间变化的数据结构,并且简化链接和共享。它还有助于为不同的段提供不同的保护。又是,分段和发呢也组合在一起提供一个二维的虚拟存储器。MULTICS系统和Intel Pentium支持分段和分页。