mirror of
https://github.com/Didnelpsun/CS408.git
synced 2026-02-09 05:44:32 +08:00
Update 2-memory-management.md
This commit is contained in:
@@ -224,10 +224,94 @@
|
||||
|
||||
将页表进行分组离散地放入内存块,并为离散分组的页表再建立一张页表,称为页目录表、外层页表或顶层页表,页目录表页保存序号和内存块号两项。两级页表结构的逻辑地址结构分为一级页号、二级页号和页内偏移量三项。
|
||||
|
||||
地址转换过程:
|
||||
|
||||
1. 按照地址结构将逻辑地址拆分成三部分。
|
||||
2. 从PCB中读出页目录表始址,再根据一级页号查页目录表,找到下一级页表在内存中的存放位置。
|
||||
3. 根据二级页号查表,找到最终想访问的内存块号。
|
||||
4. 结合页内偏移量得到物理地址。
|
||||
|
||||
注意点:
|
||||
|
||||
+ 若采用多级页表机制,则各级页表的大小不能超过一个页面。因为顶级页表只能有一个,否则一个页面放不下页表项。如果一个页面框放不下就需要多个页面框,而如果需要多个页面框就会导致多个页面框有相同的页号,就不能区分出哪个是顶级页表。
|
||||
+ 两级页表的访存次数分析(假设没有快表机构):
|
||||
1. 第一次访存:访问内存中的页目录表。
|
||||
2. 第二次访存:访问内存中的二级页表。
|
||||
3. 第三次访存:访问目标内存单元。
|
||||
|
||||
**例题** 某系统按字节编址,采用40位逻辑地址,页面大小为4KB,页表项大小为4B,假设采用纯页式存储,则要采用()级页表,页内偏移量为()位?
|
||||
|
||||
因为页面大小为4KB=$2^{12}$B,按字节编址,所以页内偏移量等于页面大小$2^{12}$B。
|
||||
|
||||
页号则=40-12=28位。
|
||||
|
||||
页面大小$2^{12}$B,页表项大小4B,则每个页面可用存放$2^{12}/4=2^{10}$个页表项。
|
||||
|
||||
所以各级页表最多包含$2^{10}$个页表项,需要10位二进制位才能映射到$2^{10}$个页表项,因此每一级的页表对应页号应该为10位,28位的页号至少分为三级。
|
||||
|
||||
#### 基本分段存储管理
|
||||
|
||||
+ 进程的地址空间:按照程序自身的逻辑关系划分为若干个不等长的段,每个段都有一个段名(在低级语言中,程序员使用段名来编程),每段从0开始编址。
|
||||
+ 内存分配规则:以段为单位进行分配,每个段在内存中占据连续空间,但各段之间可以不相邻。
|
||||
+ 分段系统的逻辑地址结构由段号(段名)和段内地址(段内偏移量〉所组成。
|
||||
+ 段号的位数决定了每个进程最多可以分几个段段内地址位数决定了每个段的最大长度是多少。
|
||||
+ 程序分多个段,各段离散地装入内存,为了保证程序能正常运行,就必须能从物理内存中找到各个逻辑段的存放位置。为此,需为每个进程建立一张段映射表,简称“段表”:
|
||||
1. 每个段对应一个段表项,其中记录了该段在内存中的起始位置(又称“基址”)和段的长度。
|
||||
2. 各个段表项的长度是相同的。某系统按字节寻址,采用分段存储管理,逻辑地址结构为(段号16位,段内地址16位),因此用16位即可表示最大段长。物理内存大小为4GB(可用32位表示整个物理内存地址空间)。因此,可以让每个段表项占16+32= 48位,即6B。由于段表项长度相同,因此段号可以是隐含的,不占存储空间。若段表存放的起始地址为R,则K号段对应的段表项存放的地址为R+K*6,段号并不占内存空间。
|
||||
|
||||
段式存储地址变换过程:
|
||||
|
||||
1. 根据逻辑地址得到段号S和段内地址W。
|
||||
2. 根据段号S是否大于等于段表寄存器的段表长度M,判断上是否越界,若是则越界中断。(段表长度至少为1)。
|
||||
3. 查询段表寄存器中的段表,找到对应的段表项,段表项分为段长C和段基址B,段表项的存放地址SA=段表始值F+段号S*段表项长度SL。
|
||||
4. 检测段内地址W是否大于等于段长C(这也是段式存储与页式存储的最大不同,段式存储不定长),若是则越界中断。
|
||||
5. 计算得到物理地址E=段基址B+段内地址W。
|
||||
|
||||
分段、分页管理的区别:
|
||||
|
||||
|与信息的关系|主要目的|是否对用户可见|长度|用户进程地址空间
|
||||
:----:|:---------:|:-----:|:-----------:|:--:|:------------:
|
||||
分页|信息的物理单位|实现离散分配,提高内存利用率|仅仅是系统管理上的需要,完全是系统行为,对用户是不可见的|页的大小固定且由系统决定|是一维的,程序员只需给出一个记忆符即可表示一个地址
|
||||
分段|信息的逻辑单位|更好地满足用户需求|一个段通常包含着一组属于一个逻辑模块的信息。分段对用户是可见的,用户编程时需要显式地给出段名|不固定,决定于用户编写的程序|二维的,程序员在标识一个地址时,既要给出段名,也要给出段内地址。
|
||||
|
||||
+ 分段比分页更容易实现信息的共享和保护。
|
||||
+ 只需让各进程的段表项指向同一个段即可实现共享。
|
||||
+ 不能被修改的代码称为纯代码或可重入代码(不属于临界资源),这样的代码是可以共享的。可修改的代码是不能共享的(比如,有一个代码段中有很多变量,各进程并发地同时访问可能造成数据不一致)。
|
||||
+ 分页时页面不是按逻辑模块划分的。这就很难实现共享。
|
||||
|
||||
#### 段页式存储管理
|
||||
|
||||
|优点|缺点
|
||||
:----:|:-:|:--:
|
||||
分页管理|内存空间利用率高,不会产生外部碎片,只会有少量的页内碎片|不方便按照逻辑模块实现信息的共享和保护
|
||||
分段管理|很方便按照逻辑模块实现信息的共享和保护|如果段长过大,为其分配很大的连续空间会很不方便。另外,段式管理会产生外部碎片
|
||||
|
||||
+ 段页式存储的过程:
|
||||
1. 将进程按逻辑模块分段,再将各段分页(如每个页面4KB)。
|
||||
2. 再将内存空间分为大小相同的内存块/页框/页帧/物理块。
|
||||
3. 进程前将各页面分别装入各内存块中。
|
||||
+ 段页式系统逻辑地址结构:
|
||||
+ 由段号、页号、页内地址(页内偏移量)组成。
|
||||
+ 段号的位数决定了每个进程最多可以分几个段。
|
||||
+ 页号位数决定了每个段最大有多少页。
|
||||
+ 页内偏移量决定了页面大小、内存块大小是多少。
|
||||
+ “分段”对用户是可见的,程序员编程时需要显式地给出段号、段内地址。而将各段“分页”对用户是不可见的。系统会根据段内地址自动划分页号和页内偏移量。
|
||||
+ 因此段页式管理的地址结构是二维的。
|
||||
+ 分为段表和页表:
|
||||
+ 每个段对应一个段表项,每个段表项由段号、页表长度、页表存放块号(页表起始地址)组成。每个段表项长度相等,段号是隐含的。
|
||||
+ 每个页面对应一个页表项,每个页表项由页号、页面存放的内存块号组成。每个页表项长度相等,页号是隐含的。
|
||||
+ 一个进程对应一个段表,对应一个或多个页表项,一个段表项就相当于只存一个的页表寄存器。
|
||||
|
||||
段页式存储地址变换过程:
|
||||
|
||||
1. 根据逻辑地址得到段号S、页号P和页内偏移量W。
|
||||
2. 根据段号S是否大于等于段表寄存器的段表长度M,判断上是否越界,若是则越界中断。(段表长度至少为1)。
|
||||
3. 查询段表寄存器中的段表,找到对应的段表项。段表项分为段号S和页表长度L段基址和页表存放块号D。段表项的存放地址SA=段表始值F+段号S*段表项长度SL。
|
||||
4. 检测页号P是否大于等于页表项长度PL,若是则越界中断。
|
||||
5. 根据页表存放块号D和页号P查询页表,找到对应页表项。页表项分为页号P和内存块号B。
|
||||
6. 计算得到物理地址E=内存块号B+页内偏移量W。
|
||||
7. 也可引入快表机构,用段号和页号作为查询快表的关键字。若快表命中则仅而次访存。
|
||||
|
||||
### 内存空间扩充
|
||||
|
||||
内存空间的扩充(用容量小的内存运行大的程序)有三种技术:
|
||||
@@ -264,3 +348,5 @@
|
||||
+ 处理机调度的中级调度(内存调度)就是交换技术的实现。进程的PCB常驻内存。
|
||||
|
||||
## 虚拟内存管理
|
||||
|
||||
### 虚拟内存的基本概念
|
||||
|
||||
Reference in New Issue
Block a user