目录:
1. 内存管理概念→程序装入和链接: a. 步骤 b. 静/动态链接 c. 运行/装入时动态链接
→逻辑地址空间和物理地址空间
→内存保护: a. 上下限寄存器 b. 重定位寄存器 & 基地址寄存器
2. 交换和覆盖→ 交换 & 覆盖
3. 连续分配管理方式→ 单一连续分配 & 固定分区分配 & 动态分区分配
4. 非连续分配管理方式→ 基本分页存储管理方式 & 基本分段存储管理方式 & 段页式管理方式
/*====================@@@@Halo World分割线@@@@====================*/
1. 内存管理概念(Memory Managment)
- 为什么要引入这个概念呢_(:3」∠ )_ 因为你太穷了,买不了好的机器,所以你只能在你的有限内存的机子上面折腾来折腾去。这样你才有足够的内存可以看苍老师的岛国动作片。(感觉这个比喻有点微妙(hmmm))没关系,学好内存管理就相当于你改造了你的破破烂烂的出租屋!让他变得very有逼格不仅看上去美观而且分配的也非常巧妙。
- 好的吧,操作系统对内存的划分和动态分配就是内存管理概念。
*内存管理的功能:a. 内存空间的分配和回收 b. 地址转换 c. 内存空间的拓展 d. 存储保护
1.1 程序装入和连接
- 创建进程后需要写入程序和数据进如内存。
【源程序→可执行程序】的过程如下:
a. 编译:由编译程序把源代码编译成n个目标模块
b. 链接:有连接程序将编译后的目标模块和库函数连接在一起,在载入到一个完整的模块里。
//(这里应该就是指你cpp文件里的include xx 这一块?)
c. 装入: 由装入程序将装入模块装入内存运行。
1)静态链接:运行前就已经把模块和库函数打包在一起,之后是不进行拆开的。//相当于这里是一次性搞定
2)装入时动态链接:源程序变异后得到的目标模块,装入内存后采用【边装边连】。//这里就是比较悠哉一点,你问我要库函数我再去找~不然我就继续装东西。
3)运行时动态链接:
a. 绝对装入 :编译程序会产生一个绝对地址,然后按照这个地址进行装入。因为是绝对的地址,所以不需要对数据和程序进行修改。*但是是适合单道程序环境
b. 可重定位装入:再多道程序坏境下,多个目标模块都是从0开始的,程序中的其他地址都是相对于这个其实地址的,此时就可以用可重定位装入方式。即,将模块放到合适的位子,之后装入对数据和指令的修改的过程就是可重定位。
c. 动态运行时装入:aka动态重定位。这个一般就是要用的时候在拿出来东西。装入程序把模块放到内存后不会马上去把相对地址转成绝对地址,而是当这个程序正真要开始执行了才动。
1.2 逻辑地址空间和物理地址空间
【逻辑地址】:编译后,每个目标模块都是从0单元开始编址的,这个就称该目标模块的相对地址 || 逻辑地址
【物理地址】:在存储器里的唯一地址
【物理地址空间】:内存中的物理单元的集合;进程在运行的时候执行指令和访问数据最后还是要通过物理地址从主存里get
1.3内存保护
- 内存分配前,需要保护操作系统不受用户进程的影响。
1. 上下限寄存器:存放用户作业在主存中的下限和上限地址,如果CPU要访问地址的话就去这两个寄存器里面做对比。
2. 通过重定位寄存器和界地址寄存器:重定位寄存器含最小的物理地址,界地址寄存器含逻辑地址的最大值。每个逻辑地址都需要这两个寄存器先核对,如果没越界的话,在映射成物理地址。
//重定义寄存器是用来‘加’的 →逻辑地址+重定位寄存器 = 物理地址
//界地址寄存器是用来‘对比’的 →通过比较界地址的值和得到的物理地址来判断有没有越界
2. 覆盖和交换
- 主要目的是为在多道程序环境中可以扩充内存的。
-覆盖是在同一个程序之间发生的,而交换是在不同程序之间发生的。
2.1 覆盖:用户空间可分固定区(放用的频率高程序)和覆盖区(即将要访问的放这里)。//代码多的时候运行起来可能就不行了(
2.2 交换:把处于等待状态的程序从内存里移到辅存,这样可以把内存空间空出来,
3. 连续分配管理方式
3.1 单一连续分配 (分为用户区和系统区)
- 系统区是给操作系统用的,通常是在低地址部分。
- 注意因为内存只有一道程序,所以他不会因为访问越界而干扰其他的程序。
3.2 固定分区分配
- 最简单的一种多道程序存储管理方式。
- 他将用户内存空间划分成好多个固定大小的区域,然后来一个作业填一个坑。
//可分 【分区大小相等】 【分区大小不相等】
a. 内部碎片
- 主存利用率低,当程序小于固定分区时候,这样会造成一个空间的浪费。这个就是内部碎片。
3.3动态分区分配
- 不预先将内部划分,而是在进程装入内存的时候,根据大小动态分配。
- 但是这样也导致了内存中会出现很多小内存块,这种内存块就叫‘外部碎片’
//但是我们可以通过紧凑来改善这个情况: 就是操作系统不断的对进程进行移动和调整。(但是这个也是需要动态重定位寄存器的支持,而且很耗时)
- 在进程装入和换出主存的时候,我们可以考虑用以下算法来搞!
a. 首次适应(First Fit):空闲分区以地址递增的次序连接。分配内存的时候顺序查找,找到可以满足大小的就插入~(但是效率低,低地址容易满,高地址容易空) //一般这个是最好的
b. 最佳适应(Best Fit):空闲的分区按照容量递增形成分区链。 找到第一个可以满足要求的空间就可以~(但是会产生碎片)
c. 最坏适应(Worst Fit):空闲分区以容量递减的次序连接。挑出最大的分区来用
d. 邻近适应(Next Fit):aka循环首次适应算法。分配的时候是从上一次查找结束的地方开始找。(但是会把空间弄得更乱)
作业道数 | 内部碎片 | 外部碎片 | 硬件支持 | 可用空间管理 | 解决碎片 | 空间不足 | 提高作业道数 | |
单道连续分配 | 1 | 有 | 无 | 界地址寄存器,越界检查机构 | / | / | 覆盖 | 交换 |
多道固定连续分配 | ≤N(用户空间N块) | 有 | 无 |
1. 上下界寄存器 2. 基地址寄存器,长度寄存器,动态地址转换机制 | / | / | ||
多道可变分配 | / | 无 | 有 |
1. 上下界寄存器 2. 基地址寄存器,长度寄存器,动态地址转换机制 |
1. 数组 2. 链表 | 紧凑 |
4. 非连续分配管理方式
4.1 基本分页储存管理方式
-把主存空间划分大小相同的块,块相对来说比较小,作为主存的基本单元。每个进程原始以块进行划分,所以进程不够用的时候,再去申请一下用块就可以了
1) 基本概念
a. 页面和页面大小:进程中的块叫‘页’(page);内存中的块叫‘页框’ (page frame);外存中的是直接叫块(block)
*页面的大小是2的整数次幂
b. 地址结构: 0-11位是页面地址,每页是4KB;12-31位为页号;地址空间里最多是2^20页
31 .... 12 | 11 ... 0 |
页号P | 页内偏移量W |
c. 页表:系统给每一个进程建立了一张页表,记录页表在内存中应对的物理块号,页表一般放在内存中。
*页式管理中地址空间是唯一的
2) 基地址变换机构
- 目的:将逻辑地址转换成内存中的物理地址,地址变换是借助页表实现的。
- 逻辑地址→物理地址的过程:
i) 计算机页号P (P = A逻辑地址 / L页面大小 )和 页内偏移量W (W = A % L)
ii) 比较页号P和页表长度M,若P ≥ M, 则产生越界,则发生中断,else继续。
iii) 页表中页号P对应的页表项地址 = 页表起始地址F x 页号P x页表项长度 (还页表项内容b是物理块)
iv) 计算 E = b x L + W,用得到物理地址E去访问内存。
3) 快表 :为了提高查找效率,在地址变换机构中搞了一个高速缓冲寄存器--快表, 又称联想寄存器(TLB)。
-地址的变换过程:
i) CPU给出逻辑地址后,硬件进行地址转坏然后在把页号给告诉缓冲寄存器,并且把页号和快表里的页号作对比
ii)如果有匹配的页号,说明页表项在快表里,则可以直接get该页对应的页框号和偏移量合体→物理地址
iii)如果没找到,那需要访问主存里的页表,在读页表项后,将其存入快表方便后面的访问。如果快表满了,则对旧的页表做替代
4) 两级页表: //这个我觉得我还不理解 = = 先mark一下,回头来补充。
*为了方便查询,顶级页表最多只有一个页面。
4.2 基本分段存储管理方式
1)分段 :短时管理方式按照用户进程中的自然段划分逻辑空间
2)段表:和页表一样,是可以查找每个段对应的内存区。
段号 | 段长 | 本段在主存的起始地址 |
3)地址变换机构
i) 从逻辑地址A中get段号S,后面的都是偏移量W!(段式问题里逻辑地址都是二进制,而页式里都是十进制)
ii) 比较段号S和段表长度M; if S >= M , 越界中断;else 继续执行
iii) 段表中段号S对应的段表地址 = 段表起始地址F + 段号S x 段表项长度; 取出该段表项前几位的段长C,
* if 段内偏移 >= C, 则 越界中断;else 继续
iv)取出段表项中起始地址b, 计算 E = b + W
*和页式管理不同在于: 段式管理不能给出一个整数然后就给你一个对应的物理地址,因为长度不固定。而且一定要知道段号和段内偏移。所以段式管理的地址空间是二维的。
*段式管理的保护方式:1. 存取控制保护 2. 地址越界保护
4.3 段页式管理方式
- 在段页式系统中,作业的地址空间被分成n段,每一段都有自己的段号,然后把每一段都分成固定大小的页。对内存靠肩的管理和分页管理是一样的,(分成若干相同的块,对内存的分配以块为单位)
*在一个进程中,段表只有一个,页表可以有好多个~
*进行一次访问是需要三次访主存的
段号S | 页号P | 页内偏移量W |