一、计算机的体系结构与内存的层次结构
(1) 计算机的体系结构
- CPU 对整个计算机软件和程序执行控制
- 内存 存储程序代码和数据
- 外设 各种各样的外设辅助程序发挥更大的功能
(2) 内存的层次结构
从上到下,CPU访问的速度由快到慢,但是他们的存储容量越来越大
(3) 操作系统的目标
- 抽象 【逻辑地址空间】
操作系统将很多底层的处理抽象成接口为上层提供服务,应用程序不需要知道底层是怎样实现的,只需要访问一个连续的地址空间即可(逻辑地址)
- 保护【独立地址空间】
在内存中,可以运行多个不同的应用程序,可能他们之间会访问其他程序的地址空间并造成破坏,所以就需要操作系统提供一种机制保护进程间的地址空间隔离开
- 共享【访问相同内容】
操作系统提供一种进程间能够安全、可靠、有效的数据传递机制
- 虚拟化【更多的地址空间】
操作系统将当前的程序加载到内存中,然后暂时用不到的从内存中移动到磁盘上,这样内存中的空间就好像扩大了一样,虚拟出来更多的空间。
举个栗子:
从图中可以看出,在操作系统下有 p1~p4 四个放在内存中的程序,正在占用CPU运行的程序为P1,P2、P3、P4处于等待状态,正在运行的P1可能需要更多的空间,所以P4当前访问的数据没必要放到内存中,操作系统就将P4存储到了硬盘上
二、地址空间和地址生成
(1)什么是地址空间?
- 地址空间分为物理地址空间和逻辑地址空间
- 物理地址空间:由内存、硬盘等提供的实际的存储空间
- 逻辑地址空间:由应用程序假想出来的一段连续的地址空间,最终还会落实到物理地址空间上
(2)地址空间是怎么生成的?
逻辑地址空间的生成: 主要分为编译、汇编、链接、载入几个步骤
-
以C程序(.c)为例,对于逻辑地址空间的生成是由编译器提供的
-
C程序通过编译得到汇编程序(.asm)
C 程序中函数的位置和变量的名字都属于它的逻辑地址,更加便于人理解
汇编程序接近机器语言,用符号代表函数和变量名,更加便于机器去理解 -
汇编语言通过汇编程序转化为机器语言的程序(.o)
机器语言可以把函数名和变量名转化成对应的地址,生成的地址是从零开始的连续的地址空间 -
通过linker将多个机器语言程序转化为单一的可执行程序(.exe)
属于可以在内存中执行,目前存放在硬盘中的程序,对逻辑地址进行全局的划分,不同机器语言程序访问不同的地址空间 -
硬盘中的执行程序通过loader放到内存中去运行
从符号表示的逻辑地址到可以在内存中运行的逻辑地址,整个过程不需要操作系统参与
逻辑地址映射到物理地址:
-
当CPU要执行某条指令时,它的ALU(计算逻辑单元)部件需要这条指令的内容,它会发出一条参数为指令逻辑地址的请求
-
CPU 中的MMU(内存管理单元)会去查找这个逻辑地址的映射表中是否存在对应的物理地址
-
CPU 的控制器会给计算机的主存发出一个请求,需要某一个物理地址的内容,内容就是指令的内容
-
主存会将内存的内容通过总线传给CPU,CPU获得指令之后就可以执行指令
操作系统需要在逻辑地址转化为物理地址之前将这个逻辑地址与物理地址的关系建好,这个关系可以放在内存中由CPU进行缓存,从而加快访问过程
(3)操作系统如何保护不同的进程之间相互不干扰?(安全检查机制)
操作系统确保每个应用程序访问的地址空间是合法的,并且限制在它的约束范围之内。
通过起始地址和偏移地址知道,有一块区域属于这个应用程序合理访问范围
三、连续内存分配【针对一块连续区域展开讨论】
1. 内存碎片问题
- 当我们给一个运行的程序分配一块空间之后,会出现有一些无法进一步利用的空闲空间碎片
- 碎片有分为 外部碎片 和 内部碎片 两种
内部碎片:在分配单元 中 未使用的内存 【没分配出去的部分】
外部碎片:在分配单元 间 未使用的内存 【分配给了应用程序,但应用程序无法进一步使用】
2. 分区的动态分配
- 操作系统应该什么时候提供一个连续内存空间的分配 ?
(1) 操作系统将应用程序从硬盘加载到内存中,这就需要分配一块连续的空间让应用程序运行
(2) 在应用程序运行的时候需要访问数据,就需要操作系统给这些数据分配一块连续的内存空间
- 为了管理这些空闲与非空闲的内存空间,操作系统提供三种动态分配的机制:【如何分配】
首次适配、最佳适配、最差适配 三种分配策略
(1)首次分配
- 从低地址开始寻找第一个比需求空间大的内存地址快
- 实现需求:
按照地址排序、根据大小匹配、相邻重分配
- 优势与缺点:
优势:容易产生较大的剩余空闲块,如果与其他空闲块相邻的话,那么就会提高重分配的效率【指的是 从没使用的地址开始,直到末尾,这部分的合并】
缺点:把当前块分配掉了,当下一次分配时就要从下一个块开始考虑【如果分配后都有剩余,那么持续一段时间后就会显得对内存的利用率并不是很高】
(3)最优分配
- 从所有内存块中,找出最适合用来分配给当前应用程序或数据的【与需要的空间差值最小】
- 实现需求:
按照尺寸排序、根据大小匹配、相邻重分配
- 优势与缺点:
优势:避免了分割大的空闲块,使外部碎片尽可能的小
缺点:剩余很多很小的空间,不利于后续空间的管理
(3)最差分配
- 从最大的内存块开始分配给需要的应用程序或数据
- 实现需求:
按照尺寸排序、大块优先匹配、相邻重分配
- 优势与缺点:
优势:避免了产生太多小内存块,适用于为中尺寸的需求分配空间
缺点:在后续分配过程中无大块内存可用,重分配慢
3. 压缩式碎片整理
- 通过调整运行时程序的位置,来使剩余的连续内存块更大【内存拷贝】
- 什么时候去重定位 ?
程序等待的时候去执行操作,如果程序正在执行那可能造成数据丢失【比如正在读或写行为】 - 开销情况 ?
对于拷贝内存的开销是很大的,如果重复执行很多次可能会起到相反的作用,降低了效率
4. 交换式碎片整理
- 通过将内存中等待的应用程序移动到硬盘中,来扩大内存空间【当需要这个应用程序执行的时候再拷贝回来】
后续会对 选择哪个等待程序拷贝到硬盘中 以及 什么时候去执行换入换出操作 进行讲解!