一、死锁
1.必要条件:
互斥
请求和保持
不可抢占
循环等待
2.处理死锁的办法
不管
预防:防止四个条件中的一个出现
避免:优化资源分配,让系统除于安全
检测:不预防,及时检测出死锁
解除:出现死锁,想办法解除
检测和解除是一体的
防范程度逐渐下降,但是资源利用率逐渐提高
3.避免死锁的办法 (破坏三个死锁必要条件)
1.互斥条件一般不可破坏
2.破坏请求和保持
a.要申请必须申请全部资源
b.申请一部分,释放后,再申请其他资源
3.破坏循环等待
给资源编号,进程按照编号顺序来请求资源
4.破坏不可抢占
如果申请其他资源失败了,就释放原有资源
4.避免死锁的办法
原理:系统处于安全状态,就不会发生死锁
操作:系统每次分配资源之前,都检测分配是否会让系统进入不安全状态,如果不会就分配资源,否则,进入等待
经典算法:银行家算法
5.死锁的检测和解除
原理:简化资源分配图,如果不能简化为孤立节点,说明有死锁。
死锁解除算法:
1.终止进程
2.抢占资源
3.回滚
二、内存
1.存储器的层次
分为CPU寄存器,主存,辅存三层。
CPU寄存器包括寄存器,主存包括高速缓存、主存、磁盘缓存(逻辑上的,实际属于主存的一部分),辅存包括固定磁盘和可移动存储介质。
其中,寄存器速度和CPU差不多,主存和CPU速度差很多,CPU寄存器和主存都属于操作系统管理,断电后信息失效,称可执行存储。
高速缓存用于备份重要数据,位于主存和CPU之间,用于缓解主存和CPU之间的速度关系。
2.程序的装入和链接
1.编译:编译器对源代码进行编译,成多个目标模块
2.链接:将目标模块和库函数链接成装入模块
3.装入:装入程序将装入模块装入内存
3.装入的方式
(1)绝对装入
编译后直接产生物理地址。
(2)动态可重定位装入
把在装入中对目标程序中指令和数据地址的修改过程称为重定位。又因为地址变换通常是在进程装入时一次完成的,以后不再改变,故称为静态重定位。
动态可重定位装入时的物理地址和逻辑地址不同,不允许运行时修改;可将装入模块装入内存中任何允许的位置,可用于多道程序环境。
(3)动态运行时装入
把装入模块装入内存后,并不立即把逻辑地址转换成物理地址,而是在运行时才进行地址的转换,需要重定位寄存器的支持。
4.链接方式
(1)静态链接
将目标模块和库函数链接成装入模块,此后不再拆开
(2)装入时动态链接
边链接边装入,装入时若发生外部模块调用事件,先将外部目标模块装入内存。
(3)运行时动态链接
运行时需要某个模块再去链接装入,没用到的不链接装入
5.内存分配方式–连续
程序必须被分配在连续的内存空间,不能分开。
(1)单一连续分配:
只有一个程序,除了操作系统以外都是程序
(2)固定分区分配
多程序,将内存分为多个固定的分区,分区有相同和不同;有分区表之类的存储分区信息。
(3)动态分区分配
可以按照程序大小进行分配。
i.数据结构
1.空闲分区表:
2.空闲分区链:
ii.动态分区分配算法:
基于顺序搜索的动态分区分配算法:
1.首次适应算法(FF,First Fit)
从链首开始查找,知道找到满足要求的空闲分区,然后按照作业大小画出一块内存空间,剩余的空闲分区仍留在空闲链。
缺点:查找从低地址开始,保留了高地址的空闲区,为大作业留出位置,但是低地址被不断划分,留下碎片每次从低地址开始找就增加了查找花销。
2.循环首次适应(next fit,NF)
不再从链首开始查找,而是从上一次找到的空闲分区的下一块开始查找。
优缺点:减少了查找开销,但是缺乏大的空闲分区。
3.最佳适应算法(BF)
要求:空闲分区按容量大小排序,小的在前
每次查找最贴近要求的空闲分区
缺点:留下过小的碎片
4.最坏适应(worst fit,WF)
要求:将空闲分区按照从大到小的顺序排序
每次查找总是挑选最大的分区,从中分割一部分存储空间给作业使用,因为排序了,查找时总是看第一块分区是否符合要求即可
优缺点:缺乏大的空闲分区,但是产生碎片的可能性最小
基于索引搜索的动态分区分配算法:
1.快速适应
2.伙伴系统
3.哈希算法
建立哈希函数,构造空闲分区大小为关键字的哈希表,根据所需分区大小,通过哈希函数计算,得到在哈希表中的位置,从中得到相应的空闲分区链表,实现最佳分配策略。
iii.动态可重定位分区分配:
iiii.操作:
1.分配内存
2.回收内存
以上三种情况都可以将回收区和空闲区合并。
注意:
(a)不必为回收区分配新表项,只需求改F1的大小
(b)用回收区首地址作为新空闲区首地址。
回收区上下都没有空闲区,单独建立新表项,写回收区首地址和大小,根据首地址插入到空闲链适当位置。
6.对换
系统将暂时不运行的进程和不需要的数据和程序调入外存,将外存上具备运行条件的进程和需要的数据和程序调入内存。
linux中有个/swap专区供对换使用。
对换有关知识连接:对换
7.内存分配方式-离散
(1)分页存储管理
分页存储管理将进程的逻辑空间分为若干页,也将内存的物理空间分为若干块,都加以编号;在为进程分配内存时,以块为单位,将进程的若干页装入多个可以不相邻接的物理块中。
页面大小过大,碎片过多;太小,页表占内存多,进程占用过多页,换进换出效率低。
页表存储了页号和物理块号的映射关系。
地址结构:
W即页内地址。
页面大小*页号+页内地址=一个完整的逻辑地址
未添加快表寻址过程:
需要页表存储器存储页表起始地址和页表大小。
添加快表(联想寄存器,TLB)之后的寻址过程:
先到快表中查找,若在,直接读出所属物理块号,送到物理地址寄存器;若不在,到内存中的页表查找,找到后将物理块号送到物理地址寄存器,同时将此页表项存入快表的一个寄存器单元中,若快表已满,将老的被认为不再被需要的表项换出。
(2)分段存储管理
根据程序员需求而诞生,每个段都有自己的逻辑含义,页是没有的。
分段意义:
1.方便编程:通过段名+段内地址来访问数据更方便
2.信息共享:可以为共享过程建立独立的段
4.信息保护:类似共享,信息保护的单位也是一个逻辑数据。
5.动态增长:对于大小不确定的数据可以分段
分段的基本原理
段的信息共享
允许多个进程共享一个或多个分段
(3)段页存储管理
分段和分页结合。
先分段,段内分为若干页,地址结构为段号,段内页号,页内地址。
既有段表,也有页表,段表存储的是页表起始地址和页表长度。
共访问三次内存:
1.访问段表的对应段表项
2.根据段表项里的页表长度和页表基址+段内页号,访问对应的页表项
3.根据块号+页内地址访问内存
改进也是通过高速缓存。
8.访问内存的时间
无快表:徐访问两次内存,第一次访问页表,找到物理块号,将块号和页内偏移拼接得物理地址;第二次根据物理地址访问内存获得所需数据。t为访问一次内存的时间。
有快表:需要考虑命中率的问题
a是命中率(在快表中成功找到所需页面表项的比率),接近1时,整体只需要访问一次内存+快表。londa表示访问快表需要的时间。
9.两级页表和多级页表
原因:现在的计算机操作系统都支持非常大的逻辑地址空间,这样的话,页表就会变得非常大,而且进程要求页表是连续的,这就不现实,所以需要优化页表本身的存储。
(1)两级页表
可以看出页表的每个表项存储的是页号和物理块号的映射关系,而外层页表的每个页表项存储的是某页表分页的首址,如0#页表存放在#1011物理块中。
地址结构:
解决了对于大页表无需大量存储空间的问题,但未解决用较少的内存空间去存放较大页表的问题。想要减少页表空间,采用部分调入页表项,然后根据需求再调入。