【操作系统基础】分段和分页

前言

分段和分页的出现:就是为了解决以前操作系统设计管理内存方案(连续分配内存管理方案)带来的问题而设计出的一种新管理内存的方案;


大概意思就是:一个进程不是完完整整的放入到连续的内存区域,而是把进程分段放入内存,因为把进程连续的放入内存带来的问题就是碎片问题很严重,所以分段放入内存就可以有效的缓解碎片问题;


在这里插入图片描述


但是将进程分段放入内存,也会带来一个新的问题,这些分段的数据被放到哪里了?
此时就需要操作系统维护一张表来记录了,这时候操作系统又会增加了新的负担,把进程分片,放入内存,计算内存哪儿有空位,计算表的数据等等等;
但是它解决了碎片问题带来的收益是大于连续内存分配的策略方案的;
对于操作系统这种哲学问题设计方案,我们认为是可行的;


分段的动机

在这里插入图片描述


分段动机就是为了解决内存管理带来的碎片问题的一种机制,分段允许逻辑地址空间的进程放入内存是不连续的,也就是说在内存的进程不是连续排列的,而是七零八落散落各个位置;
在我们程序员的眼中:内存是可变大小的段而已,也就是说,其实我们是把内存看成一个个分区而已;
而在我们真实的物理内存视角:内存就是一个一个字节组成的;
所以基于程序员的视角和OS看到内存的视角不一样,我们就需要一种管理内存的机制;
所以说:在硬件上,我们提供了一种内存机制它可以把程序员眼中的逻辑地址映射到时机的物理内地址;这个硬件就可以帮助我们转化视角管理内存;


分段

在这里插入图片描述


在这里插入图片描述


比如上图:我们左图0-13把它想象为14条指令,把这14指令按程序员的逻辑划分段,那么就画出右图的3个段;
注意:划分出来的段的逻辑地址都是从0开始的;
当段划分好了,我们还需要记录划分每一个段的编号,要不然就找不到对应的指令了;
比如我想找void g函数里的1逻辑地址的指令,我们是如何找到呢?首先找到 段的编号seg#1,其次再偏移1位就找到了;
在分段的机制下,一个逻辑地址就被分成:《segment-number,offset》


分段机制逻辑转物理地址

在这里插入图片描述


我们知道:分段机制的逻辑地址位:<段号,段内位移>组成,但是我们逻辑地址如何转换位物理地址呢?
首先:我们得知道一些信息,1,段号对应的基地址是什么,2. 段号对应的地址范围是什么?
为什么需要知道这个信息才可以算出物理地址?
因为知道段号基地址,那么我们找到 段号,再找到基地址,就可以基地址+段内位移形成物理地址了;
段号对应范围主要是用来保护内存不越界的。


理一理逻辑:
首先在分段机制下:为了管理内存,我们的逻辑地址为:<段号,段内位移>组成;
其次为了让逻辑地址映射到物理地址,OS需要维护一张表,该表名字就是段表;
段表里记录三个信息:1. 段号,2.段内基地址,3.段的大小;
当我们逻辑地址需要转为物理地址时候:
需要先查找逻辑地址的段号,根据段号去段表查找该段的基地址,还有段的大小;
再把段的基地址,和段的大小放入两个寄存器:base 和 limit 两个寄存器种;
再拿到limit寄存器的值,也就是段的大小,和逻辑地址的段内位移比较;
段内唯一比段的大小大,就是非法地址,段内唯一比短的大小小就是合法地址;
合法地址就把段内位移加上base寄存器的值,也就是段内基地址,这样就找到了物理地址;


分页

分页的诞生也是分段管理的跃迁版本,分段管理虽然减少了内存碎片,但是减少的还是不够多,多多少少还是会又内存碎片的,我们OS为了合理的榨干内存的空间,进一步减少内存碎片问题,又搞出来一个机制就是分页;


在这里插入图片描述


上图左边是内存,右边是程序,我们分页的基本思路就是:
把内存分为固定大小的分区,程序也被切成固定大小分区;
内存固定大小的分区,我们叫页框,也是帧frames,而程序的固定大小分区我们成为页面,也是pages;
这样,程序就可以零零散散的放入到内存种了,很明显:页框的大小是等于 页面的大小的

分页也会产生内存碎片,但是这个内存碎片式可控的;
比如上图的程序,被分成了10个页面,因为页面都是固定大小的,这就说明再上程序分页的过程中,只有最后一个页面10个才不是固定大小的;
假设固定大小为4kb,而程序只有39kb的大小,那么分10个页面,只有第10个页面的大小为3kb,其他页面的大小都是4kb;
当把程序的每个页面都放进内存的也框中,只有第10个页面是占页框的3kb,页框就会剩下1kb,这也是内部碎片的产生,但是这个内部碎片太小了,我们控制的还是相当合理的;


在这里插入图片描述


上图的意思是,把程序的所有页面都加载到了内存中,并且操作系统会维护一个页表,页表记录着页框和页面映射关系;


页号与页内位移

有了分页机制,我们的逻辑地址就可以表示为:页号+页内位移了;
在这里插入图片描述


比如上面的程序,我们又12条指令,假设每条指令1kb,我们把它划分为固定大小的页面是4kb,所以该程序就划分为了3个页面,而这三个页面分别由自己的编号,也就是页号,每个页号里面的就是页内位移;


分页机制逻辑地址转物理地址

在这里插入图片描述


在分段机制,下我们的逻辑地址为(页号,页内位移)组成;
当我们程序加载到内存,操作系统就会维护一张页表,页表记录着页框号与页号(每个页面的编号就是页号)的映射关系;
逻辑地址转物理地址就可以通过逻辑地址的页号,找到对应的页框,然后页框号乘于页框大小加上页内位移就得到了逻辑地址;


虽然上面的方式可以算出物理地址,但是在OS内部缺不是这么算的,OS内部是直接通过:把逻辑地址的页号,替换成页号对应的页框,让后就和页内位移直接组合成物理地址;

具体的原理我们可以通过上面的逻辑地址计算物理地址的公式来推导;
在这里插入图片描述


OS内部将逻辑地址转换为物理地址的硬件运行机制原理;
把拿到逻辑地址,提取到页号p,从页表找到对应的页框f,再把页号替换成f,逻辑地址就出来了;
在这里插入图片描述


分页机制的逻辑地址

在这里插入图片描述


在分页机制下,页面大小和页框大小都是硬件所设定的,**这个页面大小有规定,必须是2的多少次幂,**页面大小不同的计算机体系架构都不一样,页面的大小一般都是从512字节到1GB范围,通常我们Linux计算机体系下的页面的大小就是4kB
为什么说页面的大小必须是2的多少次幂,原因就是为了加块逻辑地址到物理地址的转化和简易性;
如果我们的逻辑地址空间为2m的话,说明逻辑地址的bit位数就有m个;
并且页面的大小为2n的话,那么就说明页内位移就是n个bit;
那么我们就可以得知,一个逻辑地址:页号的bit位数就是m-n了;


分段和分页的区别

在这里插入图片描述


分段的是以信息逻辑单位划分内存空间,也就是每个程序的空间,是一个一个逻辑划分的,比如一个函数一个函数的逻辑单元;而分页就是固定大小的空间划分的;

猜你喜欢

转载自blog.csdn.net/m0_46606290/article/details/124420320