内存
- 内存用于存放数据的硬件,程序运行前需要先放到内存中才能被cpu处理
- 如何区分程序的数据存放在内存的什么地方?----给内存的存储单元编地址,从0开始每个地址对应一个存储单元,如果按字节编址则每个存储单元大小为一个字节。
逻辑地址与物理地址
我们写的代码需要翻译成cpu能识别的指令,这些指令会告诉cpu应该去哪个地址操作数据。数据的实际存放地址就是物理地址,但是实际上在生成机器指令的时候并不知道该进程的数据会被放到什么位置,所以编译生成的指令一般是使用逻辑地址。
物理地址(绝对地址):实际放入内存中的地址,装入模块装入内存时,需要对指令中的地址进行处理
逻辑地址(相对地址):编译时产生的指令只关心相对地址,即相对于开始地址而言的地址
装入的三种方式
三种链接方式
1、内存管理的概念
包括内存管理和虚拟内存管理。
内存管理包括内存管理概念、交换与覆盖、连续分配管理方式和非连续分配管理方式(分页管理方式、分段管理方式、段页式管理方式)。
虚拟内存管理包括虚拟内存概念、请求分页管理方式、页面置换算法、页面分配策略、工作集和抖动。
操作系统对内存的划分和动态分配,就是内存管理的概念
2、覆盖与交换
3、连续分配管理方式
4、非连续分配管理方式(分页管理方式、分段管理方式、段页式管理方式)。
一、分页存储管理
- 基本概念
将内存空间分为一个个大小相等的分区(称为页框),每个页框具有页框号。
将用户进程的地址空间也分成与页框大小相等的一个个区域(页、页面),每个页面的编号称页号。
(最后一个页面可能没有一个页框那么大,所以页框不能太大,否则可能产生过大的内部碎片)
进程的页面与内存的页框一一对应 - 基本地址的转换
- 页表
为了能知道每个页面在内存中的存放位置,os要为每个进程创建一张页表
1、一个进程对应一张页表
2、进程每一页对应一个页表项,页表项连续的存放在内存中
3、每个页表项由页号和块号(页框号)组成
4、页表记录进程页面和实际存放的内存块之间的对应关系
5、页表项长度相同,页号隐含
- 具有快表的地址变换机构
1、原理:由局部性原理,可能连续多次查到的都是一个页表项
2、快表(TLB):存放最近使用过的页表项,快表存放在更高速的存储器中
3、引入快表后地址变换过程:
- 两级页表
1、单级页表的问题:
-页表需要连续存放,因此当页表很大的时候需要占用很多个连续的页框
-没有必要让整个页表常驻内存,因为进程一段时间内可能只需要访问某几个特定的页面。
2、解决思路:
-将长长的页表进行分组,使得每个内存块正好放入一个分组,然后为离散的页表再创建一个页表,称作页目录项
-在需要访问页面时才把页面调入内存(虚拟存储技术),在页表项中增加一项表示页面是否在内存中,如果想访问的页面不在内存中,则产生缺页中断(内中断),然后将目标页面调入内存
二、分段存储管理
-
基本概念
程序按照自身的逻辑关系划分为若干个段,内存分配则按照段为单位进行分配,每个段在内存中占有连续空间,各段之间可以不相邻。
-
段表
每个进程建立一张段表,记录逻辑段到实际存储地址的映射关系
段表:段号(隐含)+段长+基址(该段在内存中的起始地址)
每个段对应一个段表项 -
地址变换
-
分段vs分页
三、段页存储管理
- 基本概念
进程按照逻辑模块分段,各段分页,内存空间分成大小相同的内存块/页框
- 逻辑地址结构
段 – 段表项 — 段号,页表长度,页表存放块号 ---- 内存块号 - 总结
虚拟内存
1、局部性原理
- 时间局部性:
如果执行了程序中的某条指令,那么不久之后这条指令就可能再次执行;如果某个数据被访问过,不久之后该数据可能再次被访问;(因为程序中存在大量循环) - 空间局部性:
一旦程序访问了某个存储单元,在不久之后,其附近的存储单元也很有可能被访问(因为很多数据在内存中是连续存放的,并且程序的指令也是顺序地 在内存中存放的) - 高速缓冲技术
思想:将近期会频繁访问到的数据放到更高速的存储器中,暂时用不到的数据放在更低速存储器中。(类似快表的思想)
2、虚拟内存的定义和特征
- 定义:
基于局部性原理,程序装入时,将程序中很快会用到的部分装入内存,暂时用不到的部分留在外存
程序执行过程中,所访问的信息不在内存的时候,由os负责将所需要的信息从外存调入外存,然后继续执行程序。
若内存空间不够,os会负责将内存中暂时用不到的信息换出外存
这样在os的管理下,用户看起来似乎有一个比实际内存大的多的内存,这就是虚拟内存 - 特征
- 虚拟内存的容量
最大容量:由计算机的地址结构(cpu寻址范围 )确定
实际容量:min(内存和外存容量之和,cpu寻址范围)
3、如何实现虚拟内存技术
- 总结一下虚拟内存是怎么工作的
当每个进程创建的时候,内核会为进程分配4G的虚拟内存,当进程还没有开始运行时,这只是一个内存布局。实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射)。这个时候数据和代码还是在磁盘上的。当运行到对应的程序时,进程去寻找页表,发现页表中地址没有存放在物理内存上,而是在磁盘上,于是发生缺页异常,于是将磁盘上的数据拷贝到物理内存中。
另外在进程运行过程中,要通过malloc来动态分配内存时,也只是分配了虚拟内存,即为这块虚拟内存对应的页表项做相应设置,当进程真正访问到此数据时,才引发缺页异常。
可以认为虚拟空间都被映射到了磁盘空间中(事实上也是按需要映射到磁盘空间上,通过mmap,mmap是用来建立虚拟空间和磁盘空间的映射关系的) - 利用虚拟内存机制的优点
既然每个进程的内存空间都是一致而且固定的(32位平台下都是4G),所以链接器在链接可执行文件时,可以设定内存地址,而不用去管这些数据最终实际内存地址,这交给内核来完成映射关系
当不同的进程使用同一段代码时,比如库文件的代码,在物理内存中可以只存储一份这样的代码,不同进程只要将自己的虚拟内存映射过去就好了,这样可以节省物理内存
在程序需要分配连续空间的时候,只需要在虚拟内存分配连续空间,而不需要物理内存时连续的,实际上,往往物理内存都是断断续续的内存碎片。这样就可以有效地利用我们的物理内存