操作系统学习笔记——第四章 存储管理

在学习操作系统时总结了笔记,并分享出来,特别是蓝色和红色字体。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

参考书:《操作系统》谌卫军等,清华大学出版社,2012年5月
参考视频:清航全套计算机专业课视频

目录

第四章 存储管理

1.单道程序存储管理

2.分区存储管理

3.页式和段式存储管理

4.覆盖技术和交换技术

5.虚拟存储技术

第四章 存储管理

1.单道程序存储管理

理想中的存储器:更大、更快、更便宜的非易失性存储器。

实际中的存储器?

存储管理?一般讲的是内存

-内存分为两个区域:系统区,用户区。每次把一个应用程序装入到用户区运行,由它和操作系统来共享内存。当它运行结束后,操作系统再装入一个新的程序把它覆盖;

-优点:简单、开销小,易于管理;

-适合于单用户、单任务的OS。

缺点?

-每次只能运行一个程序

-内存资源的使用效率不高——程序较小时,会浪费大量的内存空间

-OS的保护——应用程序的bug会破坏OS

-地址空间有限——即为物理内存的大小

2.分区存储管理

-内存分为两大区域:系统区,用户区。又把用户区划分为若干分区(partition)。一个进程占用一个分区。

-特点:适合多道程序系统和分时系统,支持多个程序并发执行。

固定分区存储管理:各个用户分区的个数、位置和大小一旦确定以后,就固定不变。

分区的大小是否相等?

-程序大小不同

-多个小分区、适量的中等分区、少量大分区

进程个数多于分区个数?

-输入队列

固定分区的缺点:

-内存利用率不高,内碎片造成很大浪费。所谓内碎片,即进程所占用分区之内的未被利用的空间。

-分区的总数固定,限制了并发执行的程序个数,不够灵活。

-地址空间的大小有限。

-如何确定分区的大小?

可变分区(动态分区)

-初始时,操作系统会占用内存的一部分,其余空间为一个完整的大空闲区

-当一个程序要求装入内存运行时,系统从这个空闲区中划一块分配给它

-当程序完成后释放所占用的存储区

-随着一系列的内存分配和回收,原来的一整块大空闲区就形成了若干占用区和空闲区相间的布局。

可变分区的特点

-分区的个数、位置和大小都是随进程的进出而动态变化的,非常灵活,避免了在固定分区中因分区大小不当所造成的内碎片,提高了内存利用率。

-有外碎片,即各个占用分区之间难以利用的空闲分区。

-使得内存的分配、回收和管理更为复杂。

如何实现可变分区的存储管理技术?

1)内存管理的数据结构;

2)内存的分配算法

3)内存的回收方法

4)碎片问题

分区分配算法:当一个新进程到来时,需为它寻找某个空闲分区,其大小必须大于或等于该进程的要求。若大于要求,则将该分区分割成两个分区,其中一个分区为要求大小并标记为“占用”,另一个分区为余下部分并标记为“空闲”。

分区分配算法主要有:最先匹配法、下次匹配法、最佳匹配法、最坏匹配法。

地扯映射(重定位)

1)物理地址

-也叫内存地址、绝对地址,实地址;

-把内存分成很多个大小相等的存储单元,每个单元给一个编号,这个编号称为物理地址:

-物理地址可以直接寻址;

-物理地址的集合称为物理地址空间(内存地址空间),它是一个一维的线性空间。

2)逻辑地址

-也叫相对地址,虚地址;

-用户程序经汇编或编译后形成目标代码,目标代码通常采用相对地址的形式,其首地址为0,其余指令中的地址都是相对首地址来编址;

-不能用逻辑地址在内存中读取信息。

3)地址映射

-为保证CPU执行指令时可正确访问存储单元,需将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址,此过程称为地址映射。

为了保证CPU执行指令时可正确访问存储单元,在装入程序时必须进行地址映射,将程序中的逻辑地址转换为物理地址。这主要有两种方式:

静态地址映射(静态重定位):当用户程序被装入内存时,直接对指令代码进行修改,一次性实现逻辑地址到物理地址的转换。

动态地址映射(动态重定位):当用户程序被装入内存时,不对指令代码做任何修改。而是在程序运行过程中,当需要访问内存单元时再来进行地址转换(即在逐条执行指令时完成转换)。

-由硬件地址映射机制完成,如设置一个基地址寄存器,并装入进程所在分区起始地址;

-在程序运行时,硬件自动完成地址映射。

答案:1)在CPU中,只有1个;2)准备运行时装入值

存储保护

为了防止一个用户程序去访问其他用户程序的内存分区,保护操作系统免受用户程序的破坏,须进行存储保护。

如何实现?

能否与动态地址映射集成在一起?

扩展:内存中的程序执行

进程的地址空间,内存布局是什么样的?

 1 /*全局变量,固定地址,其他源文件可见*/
 2 int global_static;
 3 /*静态全局更量,固定地址,但只在本文件中可见*/
 4 static int file_static;
 5 /*函数参数:位于栈帧当中,动态创建,动态释放*/
 6 int foo(int auto_param)//代码
 7 {
 8   /*静态局部变量,固定地址,只在本函数中可见*/
 9   static int func_static;
10   /*普通局部变量,位于栈帧当中,只在本函数可见*/
11   int auto_i, auto_a[10];
12   /*动态申请的内存空间,位于堆当中*/
13   double *auto_d=malloc(sizeof(double)*5);
14   return auto_i;
15 }

各部分分别存储哪些?

数据段:全局变量;堆空间:malloc;栈:静态局部变量、普通局部变量、函数参数

3.页式和段式存储管理

分区存储管理的特性

-连续性,这将会导致碎片问题(内碎片和外碎片)

-一个例子:容器分配方案。总容量固定,每一种物品的重量不定,且不能混合。

页式存储管理

1)基本原理

-把物理内存划分为许多个固定大小的内存块,称为物理页面,或页框(page frame)

-把逻辑地址空间划分为大小相同的块,称为逻辑页面,或简称页面(page);

-页面大小为20,一般在512字节到8K字节之间;

-当一个用户程序装入内存时,以页面为单位进行分配。若要运行一个大小为n个页面的程序,需要有n个空闲的物理页面把它装入,这些页面不必是连续的。

页式存储管理要解决如下问题:

-用于存储管理的数据结构是什么?

-当一个进程到来时,如何给它分配内存?

-当一个进程运行结束,释放它所占用的内存空间后,如何回收内存?

-当一个进程被加载到内存以后,它如何正确运行(地址重定位)?

数据结构

-每个逻辑页面存放在哪一个物理页面中?

-物理内存的管理?

存储:数组int pagetable[N]

一个例子:

内存的分配与回收算法与物理页面表的具体实现方法有关。这里以位示图为例。

内存的分配

-计算一个进程所需要的页面数N,并查看位示图,看是否还有N个空闲页面;

-若有,则申请一个页表,其长度为N,并把页表的起始地址填入PCB;

-分配N个空闲物理页面,将其编号填入页表;

-修改位示图(0→1,空闲页面数一N)

内存的回收:当一个进程运行结束,释放它所占用的内存空间后,需要对这些物理页面进行回收。

-对于每一个物理页面,根据它的编号计算出它在位示图当中的相应位置,并将相应位的值从1改成0;

-修改位示图中的空闲页面数:加上N。

地址映射

为什么要进行地址映射?

一个进程的各个连续的逻辑页面,被分散地装入到内存的各个物理页面当中,在这种情形下,怎样才能保证程序能够正确地运行?

问题描述:输入逻辑地址,输出物理地址。

(1)对于给定的逻辑地址,找到逻辑页面号和页内偏移地址;

(2)查找页表,找到相应的物理页面号;

(3)计算最终的物理地址。

页表的具体实现

页表保存在内存当中(用户/内核空间?);页表在操作系统的数据区。

-设置一个页表基地址寄存器(Page-table base register,PTBR),用来指向页表的起始地址;

-设置一个页表长度寄存器(Page-table length register,PTLR),指示页表大小。

1)硬件寄存器位于什么地方? MMU中

2)其内容何时更新?谁更新?如何更新? 进程切换时更新,由操作系统更新,从内存的PCB表去填充

备注:逻辑页面号和偏移的分离,取页表,叠加都是硬件MMU完成,页表中的内容填充,寄存器中内容的填充是CPU完成,用户程序不做任何事情。

先取出逻辑页面号,然后去访问页表,页表中有页表基地址寄存器(里边有页表的起始地址),如同用数组下标去访问数组,得到物理页面号,去和页面偏移叠加,就得到物理地址,从而访问数据。

问题:1)需访问几次内存?两次:一次访问页表(内存中),一次通过物理地址去内存数据

2)页表需不需要提前访问内存?不需要,页表基地址寄存器有物理地址(里边有页表的起始地址)

如何加快页表的查询速度?

在现有的方案中,每一次访问内存(数据/指令)时,都要做两次访问内存的工作。这样,降低了存取速度,将会影响整个系统的使用效率。

为缩短页表的查找时间,可以采用一种特殊的快速查找硬件:TLB(Translation Lookaside Buffer)或称associative memory,用来存放那些最常用的页表项。

优缺点

优点:

-没有外碎片,内碎片的大小不超过页面的大小;

-一个程序不必连续存放;

-便于管理;

缺点:

-程序必须全部装入内存;

-系统必须为每个进程维护一张页表。

Why段式存储管理?

页式存储管理(和分区存储管理)只有一个逻辑地址空间,即一维的线性连续空间,从0到某个最大的逻辑地址。但是从程序员或系统管理的角度来说,一个程序是由一组模块(片段)所组成的,每个片段是一个逻辑单元,如:主程序、全局变量、栈、库函数等。

基本原理

-对程序的每个逻辑单元(代码、数据和栈等),设立一个完全独立的地址空间,称为“段”。每个段的内部是一维的线性连续地址,大小可不同;

-对于物理内存来说,采用可变分区(动态分区)的管理方法;

-当一个程序需要装入内存时,以段为单位进行分配,把每一个段装入到一个内存分区当中,这些内存分区不必是连续的。

具体实现

-在段式存储管理中,用户空间地址为二维地址:(段号,段内偏移)。实现方式:(1)地址高端为段号、低端为偏移;(2)指令中显式地给出段号和段内偏移。

-段表:系统为每一个进程都建立了一个段表,它给出了进程当中的每一个段与它所对应的内存分区之间的映射关系。

如何实现?结构体数组

段表的具体实现:

-段表保存在内存当中;

-设置一个段表基地址寄存器(Segment-table base register,STBR),用来指向内存当中段表的起始地址;

-设置一个段表长度寄存器(Segment-table length register,STLR),用来指示段表的大小,即程序当中的段的个数;

问题1)硬件寄存器位于什么地方? MMU中

2)其内容何时更新?谁更新?如何更新? 进程切换时更新,由操作系统更新,从内存的PCB表去填充

优缺点

优点:

-程序通过分段来划分多个模块,每个模块可以分别编写和编译,可以针对不同类型的段采取不同的保护,可以按段为单位来进行共享;

-一个程序不必连续存放,没有内碎片。

缺点:

程序必须全部装入内存、外碎片等。

段式存储和页式存储各有特点:

-段式存储管理为用户提供了一个二维的逻辑地址空间,可以满足程序和信息的逻辑分段要求,反映了程序的逻辑结构,有利于段的共享、保护和动态增长;

-页式存储管理的特征是等分内存,它有效地克服了碎片问题,提高了内存的利用率。

为了保持页式在存储管理上的优点和段式在逻辑上的优点,人们又提出了段页式存储管理技术

4.覆盖技术和交换技术

过时不讲!

5.虚拟存储技术

在计算机系统中,尤其是在多道程序环境下,可能会出现内存不够用的情况,包括三种情形:

-程序太大,超过了内存的容量;

-程序太多,超过了内存的容量;

-程序太多,且单个程序太大。

大变活人,类比。盒子类似内存,桌子类似硬盘,每次钻出一人进入盒子,类似内存很小,每次调用一个程序

前提:任何时候,一个程序在运行时只有一小段会被用到,大部分还在硬盘。

这个前提是否存在?程序的局部性原理。

局部性原理(principle of locality):程序在执行过程中的一个较短时期,所执行的指令地址和指令的操作数地址,分别局限于一定区域。

局部性原理的具体表现:

-程序在执行时,大部分是顺序执行的指令,少部分是转移和过程调用指令;

-程序中存在相当多的循环结构,它们由少量指令组成,而被多次执行;

-程序中存在很多对一定数据结构的操作,如数组操作,往往局限在较小范围内。

程序的局部性原理表明,从理论上来说,虚拟存储技术是能够实现的,而且在实现了以后应该是能够取得一个满意的效果的。

成功案例:TLB、Cache。

虚拟页式存储管理

太部分虚拟存储系统都采用虚拟页式存储管理技术,即在页式存储管理的基础上,增加请求调页和页面置换功能。
基本思路:

当一个用户程序要调入内存运行时,不是将该程序的所有页面都装入内存,而是只装入部分的页面(0或多个),就可启动程序运行。在运行的过程中,如果发现要执行的指令或要访问数据不在内存,则发出缺页中断请求,系统在处理这个中断时,将外存中相应的页面调入内存,使得该程序能继续运行。

-当内存空间不够用时,需要把页面保存在磁盘上(backing store,后备存储);

-内存物理页面称为page frame,磁盘上的页面称为后备页面(backing frame);

-目的:提供一种错觉,内存的容量好像和磁盘容量一样大,且速度和内存一样快(理想状态)。

虚拟页式管理需要解决以下问题:

1)如何发现执行的代码或访问的数据不在内存;

2)代码或数据什么时候调入内存,调入策略;

3)当一些页调入内存时,内存没有空闲内存时,将淘汰哪些页,淘汰策略。

驻留位(有效位):表示该页是否在内存。若该位为1,表示该页位于内存中,即该页表项有效,可以使用;若该位为0,表示该页当前还在外存中,此时若访问该页表项,将导致缺页中断;

保护位:表示允许对该页做何种类型的访问,如只读、可读写、可执行等;

修改位:表明此页在内存中是否被修改过。当系统回收该物理页面时,根据此位来决定是否把它的内容写回外存;

访问位:如果该页面被访问过(包括读操作或写操作),则设置此位。用于页面置换算法。

思考问题:哪些位是CPU写OS读?哪些位是OS写CPU读? CPU写OS读:修改位、访问位;OS写CPU读:驻留位、保护位

问题:逻辑地址为0的物理地址是多少?划分页号(0)和页面偏移(0),通过页号(0)在页表找到2,对应物理地址为:2*4K+偏移(0)=8K=8192

问题:逻辑地址为32780的物理地址是多少?划分页号(32780/4K=8)和页面偏移(32780%4K=12),通过页号(8)在页表查找,为X,说明页面未在内存,这时候访问出现缺页中断。

在地址映射过程中,如果所要访问的逻辑页面p不在内存,则产生缺页中断(page fault)。中断处理过程:

1)如果在内存中有空闲的物理页面,则分配一页,设为f,然后转第4步;否则转第2步;

2)采用某种页面置换算法,选择一个将被替换的物理页面f,它所对应的逻辑页面为p'。如果该页在内存期间被修改过,则需把它写回外存(Where?);

-对p'所对应的页表项进行修改,把驻留位置为0;

-将需要访问的页面p装入到物理页面f当中(进程被阻塞),并修改p所对应的页表项的内容,把驻留位置为1,把物理页面号设置为f;

-重新运行被中断的指令(PC不变)。

缺页中断由MMU发出,操作系统处理中断。

页面置换算法

功能:当缺页中断发生,需要调入新的页面而内存已满时,选择内存当中哪个物理页面被置换。

目标:尽可能地减少页面的换进换出次数(即缺页中断的次数)。可把未来不再使用的或短期内较少使用的页面换出。

-最优页面置换算法(OPT,optimal)——理想情况

-最近最久未使用算法(LRU,Least Recently Used)——看时间

-最不常用算法(LFU,Least Frequently Used)——看次数

-先进先出算法(FIFO)

-时钟页面置换算法(Clock)——FIFO+跳过访问过的页面

工作集——统计了局部性原理的有效性。

页表结构

在虚拟存储技术中,虚拟内存空间往往大于实际的物理内存,现代计算机所使用的虚拟地址至少为32位,若每个页面的大小为4K,则逻辑页面的个数为220,即在页表里有220个页表项,而每个进程都有自己的虚拟地址空间。都需要自己的页表,因而占用了大量的内存空间。为解决此问题,需提出新的页表结构:

-多级页表(Multilevel Page Tables);

-反置页表((lnverted Page Tables)。

多级页表

由于不是所有的虚拟地址都会用到,所以不必把所有的页表项都保存在内存当中。以二级页表为例:

·假设逻辑地址为32位,页面大小为4K。把逻辑地址划分为两个部分:

-逻辑页面号为20位

-页内偏移地址为12位

·把逻辑页面号再进一步地划分为两个部分:

-10位的字段PT1,用来指向第一级页表当中所对应的页表项

-10位的字段PT2,用来指向第二级页表当中所对应的页表项

在学习操作系统时总结了笔记,并分享出来,特别是蓝色和红色字体。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

原文地址:https://www.cnblogs.com/Alliswell-WP/p/OperatingSystems_StudyNotes_3.html