文章目录
1.内存管理
1.1内存空间的分配与回收:
1.1.1连续分配管理
单一连续方式:内存被分为系统区和用户区,系统区(低地址)用来存放操作系统的数据,用户区(高地址)用来存放用户进程的数据,内存中只能有一道用户程序,用户程序占整个用户区空间
优点:实现简单,可以用覆盖技术扩充内存。
缺点:由于只能放入一道用户程序,有内存碎片,内存利用率极低。
固定分区分配:随着多道程序系统的出现,内存中的用户区被分成多个大小固定的分区,每个分区中放入一个用户进程。
分区大小相等的分配:灵活性很低,加入固定大小为50MB,但是有的用户进程需要100MB,有的用户进程需要3MB,前者造成了程序无法正常运行,而后者造成了内存空间的浪费。
分区大小不等的分配:由于分区大小产生的问题,于是就有了分区大小不等的分配方式,灵活性大大提高了。
那么操作系统是如何知道哪些分区被分配了?哪些分区没有被分配呢?
所以人们就设计了一个数据结构来存储各个分区的状态,每个表项对应一个分区,表项中有大小,起始地址,以及分配状况。
当某个进程要装入内存时,操作系统内核程序会根据用户程序大小检索这张表,从中找到一个能满足大小,并且未分配的,并修改对应表项中的状态。
优点:简单,无外部碎片。
缺点:
1.当用户程序太大时,可能提前划分好的分区都无法满足这个情况,所以不得不使用覆盖技术,这就降低了性能。
2.假如用户区被分为,5,5,30,30,50,50,100 ,此时如果有一个大小为60的进程要装入内存时,不得不使用100MB的分区,这就造成了内存空间的浪费,产生了内存碎片,内存利用率低。
由于固定分区分配中的分区大小不等的分配方式还是会产生内存碎片,于是就有了动态分区分配,
由于固定分区产生内存碎片的主要原因是事先分配好了分区,所以这次就干脆不要事先分配好,而是等到进程装入内存时,计算进程的所需的大小空间,于是就有了动态分区分配。
动态分区分配:在进程装入内存时,动态的建立分区。
系统用两种数据结构来记录内存的使用情况,即空闲分区表,空闲分区链
如果有多个空闲分区都能满足需求时,应该选择哪个分区进行分配呢?
进程转入内存时,按照一定的动态分区分配算法,从空闲分区表中选择一个分区分配给作业。
如何进行分区的分配与回收?
如何分配?
- 假如有一个进程5要装入内存,所需要的内存空间为4MB,它会在满足大小的分区中,修改分区的大小和起始位置,如下图。
2.如果根据动态分区算法,分配给他一个4MB的分区,于是就将这个4MB的分区从,空闲分区表和空闲分区链中对应的分区删除掉。
如何回收?
1.如果要回收的分区后边有一个相邻的空闲分区,则会将要回收的这个分区和后边相邻的空闲分区进行合并,并将分区表中,后边相邻的空闲分区更改其大小和起始地址。
2.回收区的前边有一个相邻的空闲分区,则跟上边情况一样,将两者合并,并更改前边相邻空闲分区中大小,不更改其起始地址。3.回收区的前后都有一个相邻的空闲分区,他会将三者都进行合并,将回收区后边相邻的分区从表或者链中删除掉,将前面相邻分区的大小更改为他们三个的和。
4.回收区的前后都没有相邻的空闲分区,所以就在空闲分区表或者空闲分区链中新增一条数据,表项在表中的顺序不一定按照地址递增排序,要根据动态分区分配算法来确定。
内部碎片:分配给进程的分区中,分区中有部分没用上,则会产生内部碎片,动态分区分配不会产生内部碎片。
外部碎片:由于内存中某些空闲分区太小,难以利用,如果内存中太小的分区和可以满足进程的需求,则可以通过紧凑技术来解决外部碎片。
紧凑技术:采用动态重定位的方式,让进程在内存中进行移动,将太小的空闲分区合并成一个满足进程的空闲分区,类似于“推箱子”。
1.1.2非连续分配管理
思考?
连续分配无论是固定分区分配(产生内存碎片,利用率很低,灵活性很低)还是动态分区分配(会产生越来越多的外部碎片)都会有相应的缺点。
那么是什么使他有了这些缺点呢?
就是因为他们的内存分配都是连续性的,如果允许将一个进程分散的装入到不相邻的分区中,便可避免连续分配带来的缺点,充分的利用内存。
基本分页存储的概念
基本分页存储管理
基本分页存储管理
那么采用分页管理内存的逻辑地址到物理地址是怎么变换的呢?
1.要算出逻辑地址对应的页号—>页号=逻辑地址 / 页面大小
2.要知道该页号对应的页面在内存中的起始地址
3.要算出逻辑地址在他那个页面内的偏移量–>偏移量=逻辑地址 % 页面大小
物理地址=页面起始地址+页内偏移量
第1步和第三步都可以计算出来,那么页面在内存中的起始地址该怎么得到呢?
为此,操作系统为每个进程建立了一张页表
为什么页号是隐含的呢?
别忘了,操作系统维护这个页表是为了求页号对应页表在内存中的起始地址的!!!
M号页对应的页表项一定是存放在内存地址为X(页表在内存中的起始地址)+3*M !!
那么页表存在哪里呢?页表对应的数据结构为基本地址变换结构称为页表寄存器,整体逻辑地址到物理地址的变换如下。
下图为基本地址变换结构
局部性原理:
上边的代码,多次为数组进行赋值,因为数组在内存中是连续存储的,所以会多次访问同一个内存块,那么每次通过页号去去得到对应的内存块,这个过程会循环执行很多遍,但是每次都是那一块内存块,所以有了块表地址变换机构
基本地址变换结构的改进版本->具有快表的地址变换结构
引入后地址的变换过程
===========基本地址变换机构和具有快表地址变换机构对比与总结
两级页表:
单级页表存在的问题
1.
2.
如何解决呢????????????
将单级页表分割成多个组,将各个组进行不连续存储,每个组对应一个页目录表
如何实现地址变换?
这样就解决了,在内存中需要连续的占用许多个连续的页框的问题。
这样就解决了第二个问题。
如实实现地址变换?
1.按照地址结构将逻辑地址拆分成三部分
2.从PCB中读出页目录表起始地址,根据一级页号查页目录表,找到下一级级页表在内存中的存放位置
3.根据二级页号查表,找到最终想访问的内存块号
4.根据内存块号和页内偏移量得到物理地址
基本分段存储管理
分段:按照程序的逻辑关系,将程序分为多个段,每个段都有一个段名,每个段从0开始编址。
内存分配规则:以段为单位进行分配,每个段在内存中连续存储,各个段之间可以不相邻。
> 逻辑地址分为段号和段内地址。
段号位数决定了每个进程最多可以分多少个段
段内地址决定了每个段的最大长度。
写程序时段名被编译程序翻译成对应段号,M单元被翻译成段内地址**
段表 类比于分页存储中的页表
段表等于与页表,段表项等同于页表项,段表项中由段长和基址组成。
段号是可以隐藏的,只需要知道段表的始址M(段表寄存器),就可以知道页表项的存放地址X,即X=M + 短号*段表项大小,跟跟跟分页存储管理一样!!!!!
地址变换
1.根据逻辑地址得到段号和段内地址(段内偏移量
2.判读端号是否越界(和段表寄存器中的段表长度进行对比)
3.1越界的话抛出异常
3.2不越界的话根据段表始址和段号得到段表项存放地址
4.对段内地址和段长进行越界检查
5.根据段表项得到基址
6.根据基址和段内地址得到最终的物理地址,进行访问。
分页和分段管理的对比
分段更容易实现信息的共享
因为段是信息的基本单位,所以更适合共享。栗子:假设一号段是允许共享的,如果用分段管理的话,只需要让另一个进行的段表项指向这个进程的页表项即可,但是如果是分页存储的话,各个页内可能会有不同的段,如果让另一个进程的页表项指向这个进程的页表项的话,由于页面中可能有允许共享和不允许共享的,这样就很难进行实现。
分段更容易实现信息的保护,
栗子:分段管理中,如果1号段允许其他进程访问,直接在段表项中标识是否可以访问即可,但是在分页管理中,1号段所在的页面可能有多个段,这样的话,在页表中就很难就行标识了。
在地址变换的过程中,由于每次查段表都要进行访存,所以分段中也有一个快表,类比于分页中的块表,加快访问对应物理地址的速度
段页管理方式
思想:分段和分页的优缺点
分页的优点:内存利用率高,不会产生外部碎片,只会有少量的内部碎片。
分页的缺点:不利于信息的共享和保护。
分段的优点:利于信息的共享和保护。
分段的缺点:如果段长很大的话,他就有点类似于连续分配管理了,很不方便,会产生外部碎片。
所以就有了段页管理
段页管理的逻辑地址结构
新段表和页表
段页式地址变换的机制
1.2内存空间的扩展
英雄联盟的大小为12G,那么按照之前的想法,再运行程序前,要将整个程序装入内存,然后我们发现4G的电脑也可以打英雄联盟,这是为什么呢?
定义:把物理小的内存在逻辑上拓展成很大的内存,利用了虚拟技术,操作系统的虚拟性
覆盖技术:
思想:内存中分一个固定区和若干个覆盖区。
1.程序划分为若干个功能上相对独立的程序段,按照程序逻辑结构让那些不需要同时执行的程序段共享同一块内存区
2.当有关程序段的先头程序段已经执行结束后,再把后续程序段从外存调入内存覆盖前面的程序段
交换技术:
思想:可将一些送入外存中,从而获得空闲内存空间
操作系统把一个进程的整个地址空间的内容保存到外存中(换出),而将外存中的某个进程的地址空间读入内存中(换入),换入还出内容的大小为整个程序的地址空间。
虚拟存储技术:
传统存储管理方式(连续分配,非连续分配)的特征,缺点
一次性:作业必须一次性全部装入内存才能开始运行,这就造成了两个问题。
1.作业很大时,内存空间不足,导致大作业无法运行。
2.作业量很大时,导致一些作业无法被装入内存,不能一些作业无法运行,降低了程序的并发度。
驻留性:当作业被装入内存时,所有数据都会常驻内存,知道作业运行结束。在作业运行期间,在一个时间段内只会用到作业中的一小部分数据,这就导致了内存中会驻留大量的,暂时用不到的数据,浪费了内存资源。
栗子:假如我们在玩GTA5的时候,在A场景做任务的时候,只需要加载A场景所需要的数据即可,切换到B场景的时候在把B场景所需要的数据加载到内存即可。
所以为了解决传统存储管理的缺点
我们主要从两个层面下手:1.不要让作业一次性装入内存2.把作业暂时用不到的数据放到外存中。
基于局部性原理,在程序装入内存时,我们只将他马上要用到的数据装入到内存中,暂时用不到的数据留在外存中。
程序运行过程中,加入要访问的数据不在内存中时,由操作系统将数据从外部调入到内存,然后继续执行程序。
若内存空间不够,由操作系统负责将内存中暂时用不到的信息换出外存。
在操作系统的管理下,在用户看来似乎有一个比实际内存大很多的内存,这就是虚拟内存。
虚拟内存的主要特征:
多次性:不需要把作业一次性装入内存,而是允许多次从外存调入内存。(对应传统存储的一次性)
对换性:作业运行时无需一直常驻内存,而是允许在运行过程中,将作业换入,换出。
虚拟性:从逻辑上扩充了内存的容量,让用户觉得内存远大于实际内存的容量。
虚拟内存的实现是建立在离散分配内存管理的基础上的。
虚拟内存的实现:
在程序执行过程中,当要访问的数据不在内存中时,由操作系统将数据从外存调入内存(操作系统要提供请求调页(段)的功能)。当内存空间不足时,要将内存中暂时用不到的数据换出外存(操作系统要系统页面(段)置换的功能)。
请求分页存储管理:
请求分页存储管理和基本分页存储管理的主要区别就是请求分页在访问的数据不在内存中时,由操作系统将要访问的数据从外存调入内存,若内存空间不足,将内存中用不到的数据换出到外存
请求分页的管理方式:页表机制,缺页中断机构,地址变换机构。
页表机制:
缺页中断机构:
地址变换机构
请求分段存储管理:
请求段页存储管理:
1.3地址转换
定义 :逻辑地址重定位为物理地址,由操作系统在装入阶段进行重定位。
各个进程在内存中,是怎么保证 进程A只能访问进程A的内存空间的呢?为什么不能访问其他进程的内存空间?
1.4 存储保护:
方法一:在cpu中设置一对上下限寄存器,存放进程的上下限地址,进程中的指令要访问某个地址时,先进行比较,如果在区间内,则让其正常访问。
方法二:采用重定位寄存器和界地址寄存器进行检查。重定位寄存器存储的是进程起始物理内存,界地址寄存器存的是我最大逻辑地址。