万字操作系统总结

什么是操作系统

操作系统简述

操作系统(Operating System,简称OS)是管理计算机硬件与软件资源的计算机程序。

我们都知道,一台普通的计算机系统是由硬件和软件组成的。

我们现代计算机硬件系统一般主要由中央处理器、存储器、输入输出控制系统和各种外部设备组成。软件系统一般由系统软件(操作系统,语言编译程序,网络通讯管理系统)应用软件(办公软件,游戏软件等),支撑软件(接口软件,环境数据库软件,工具软件)组成
在这里插入图片描述
但我们一般使用计算机的时候,并不是直接和计算机的这些物理硬件打交道的,我们在使用计算机的时候,并不一定需要掌握这些系统的所有实现细节,所以我们设计出来一种管理计算机硬件与软件资源的程序–(操作系统)
让我们更方便的和计算机进行交互。

从计算机用户的角度来说,计算机操作系统体现为为其提供的各项服务;

从程序员的角度来说,其主要是指用户登录的界面或者接口;

从设计人员的角度来说,就是指各式各样模块和单元之间的联系。

操作系统的目标和作用

我们应用操作系统的目标一般和应用环境有关系,对于查询系统所用的OS我们希望其能提供更好的人机交互性;对于工业控制,需要在多媒体环境下的OS,我们要求其有更好的实时性;对于微机上的OS,我们更需要的是其方便性。

在我们计算机系统上配置操作系统,主要目标是:方便性,有效性,可扩充性,开放性。

方便性:在我们想直接在机器上运行我们所编的程序时,我们可以通过操作系统,使用编译命令,将我们采用高级语言写的程序翻译成为机器代码。不用再去运用机器语言书写程序。

有效性:我们运用操作系统可以极大的提高系统资源的利用率,可以更合理地组织计算机的工作流程,加速程序运行,缩短程序运行周期,从而提高系统吞吐量。

可扩充性:为了适应计算机硬件、体系结构及计算机应用发展的要求,OS必须有良好的可扩充性,方便添加新的功能和模块。

开放性:随着全球互连的更加开放,我们的计算机应用环境也必须更加开放,所谓开放性即我们OS能遵循世界标准规范,达到凡遵循国标开发出来的软件和硬件,都能彼此兼容,方便互连。

操作系统的发展过程

一、无操作系统的计算机系统
人工操作:
早期的操作方式是人工将事先已经穿孔的纸带或卡片,装入输入机,再启动它们将程序和数据输入到计算机,然后启动计算机运行,仅当程序运行完毕并取走计算结果时,才允许下一用户上机

脱机I/O:
事先将装有程序和数据的纸带或卡片,装入输入机,在一台外围机的控制下,把它们的数据和程序输入到磁带上,当CPU需要这些数据和程序时,再从磁带上高速调入内存

二、单道批处理系统(晶体管)
其过程为:首先,由监督程序将磁带上的第一个作业装入内存,并把运行控制权交给该作业。当该作业处理完成时,又把控制权交还给监督程序,再由监督程序把磁带(盘)上的第二个作业调入内存。计算机系统就这样自动的一个接一个作业地进行处理,直到磁带上所有的作业全部完成,这样便形成了早期的批处理系统,随是成批处理作业,但其在内存中只保持一道作业,故称为单道批处理系统。

三、多道批处理系统(小规模集成电路):
其处理过程为:在该系统中,用户所提交的作业都先存放在外存上并排成一个队列,称为“后备队列”,然后,由作业调度程序按一定的算法从后备队列中选择若干个作业调入内存,使它们共享 CPU 和系统中的各种资源。

四、分时系统:
分时操作系统 ,多个程序分时共享硬件和软件资源。分时操作系统是指在一台主机上连接多个带有显示器和键盘的终端,同时允许多个用户通过主机的终端,以交互方式使用计算机,共享主机中的资源。分时操作系统是一个多用户交互式操作系统。分时操作系统,主要分为三类:单道分时操作系统,多道分时操作系统,具有前台和后台的分时操作系统。分时操作系统将CPU的时间划分成若干个片段,称为时间片。操作系统以时间片为单位,轮流为每个终端用户服务。。满足用户对人机交互的需求。

五、实时系统:
实时系统是指系统能够及时响应外部事件的请求,在规定事件内完成该事件的处理,并控制所有实时任务协调一致的运行
实时系统的类型通常有:
(1)工业(军用)控制系统:该系统应具有实时采集现场数据,并对数据所进行及时的处理,进而能够自动的控制相应的执行机构,使之按照预先设定的方式运行功能
(2)信息查询系统:及时对终端接收来的查询服务请求进行响应,给用户端做出回答
(3)多媒体系统:为了保证良好的视听视觉感受,用于播放视频或音频的多媒体系统
(4)嵌入式系统:在智能仪器和智能设备中配置嵌入式OS,用于对设备进行控制,以及对其中的信息进行处理

六、微机操作系统:
配置在微型机上的操作系统
微机操作系统两种分类方式:

1、微型机的字长:8位、16位、32位、64位;

2、微型机运行方式:
1)单用户单任务:只允许一个用户上机,且只允许用户程序作为一个任务运行。适用于8位机和16位机。CP/M、MS-DOS;

2)单用户多任务:只允许一个用户上机,但允许用户把程序分为若干个任务,使它们并发执行,从而有效地改善了系统的性能。Windows XP;

3)多用户多任务:允许多个用户通过各自的终端使用同一台机器,共享主机系统中的各种资源,而每个用户程序又可进一步分为几个任务,使它们能并发执行,从而可进一步提高资源利用率和系统吞吐量。
Unix、Linux、Windows7;

七、网络操作系统:
网络操作系统是一种能代替操作系统的软件程序,是网络的心脏和灵魂,是向网络计算机提供服务的特殊的操作系统。借由网络达到互相传递数据与各种消息,分为服务器及客户端。而服务器的主要功能是管理服务器和网络上的各种资源和网络设备的共用,加以统合并控管流量,避免有瘫痪的可能性,而客户端就是有着能接收服务器所传递的数据来运用的功能,好让客户端可以清楚的搜索所需的资源。

操作系统的基本特性

  • 并发:计算机系统中同时存在多个运行的程序,需要OS的调度和管理
  • 共享:1、同时访问 2.互斥共享
  • 虚拟:利用多道程序设计技术,让每个用户都觉得有一个计算机专门为他服务。 利用时分复用和空分复用技术实现虚拟
  • 异步:程序的执行不是一贯到底,而是走走停停,向前推进的速度不可预知; 但是只要程序运行环境相同,OS需要保证程序的运行结果也相同。

操作系统的主要功能

1.处理机管理:

  • 进程控制:为作业创建进程、撤销已结束的进程,控制进程在运行过程中的状态转换
  • 进程同步:进程互斥、进程同步
  • 进程通信:实现相互合作进程之间的信息交换
  • 调度:作业调度、进程调度

2.存储器管理:

  • 内存分配:静态分配、动态分配
  • 内存保护:确保用户程序在自己的内存空间运行,防止其受干扰,以及防止其访问操作系统的程序和数据,不允许转移到非共享的其他用户程序上
  • 地址映射:将地址空间中的逻辑地址转化为内存空间中的物理地址
  • 内存扩充:借助虚拟技术,从逻辑上扩充内存

3.设备管理:

  • 缓冲管理:单缓冲机制、双缓冲机制、公用缓冲池机制
  • 设备分配:根据用户进程的I/O请求、现有系统资源情况、设备分配策略、为之分配所需设备
  • 设备处理:设备驱动(程序),用于实现CPU和设备控制器之间的通信

4.文件管理:

  • 文件存储空间管理:为每个文件分配必要的外存空间,提高外存利用率,进而提高文件系统的存、取速度
  • 目录管理:实现方便的按名存取
  • 文件读写管理和保护:
    文件读/写管理:根据用户请求,从外存读取数据,或将数据写入外存
    文件保护:防止系统文件被非法窃取和损坏

5.与用户之间的接口:

  • 用户接口:联机用户接口、脱机用户接口、图形用户接口
  • 程序接口:方便用户程序在执行中访问系统资源、用户获得操作系统服务的唯一途径

6.现代操作系统新功能:

  • 系统安全:认证技术、密码技术、访问控制技术、反病毒技术
  • 网络功能 与服务:网络通信、资源管理、应用互操作
  • 多媒体支持:接纳控制、实时调度、多媒体存储

操作系统的启动过程

从我们计算机的组成来看,最基本的是有三部分
在这里插入图片描述
CPU,I/O,内存通过总线相连

一开始的时候,我们的操作系统是并没有放在内存里边直接让CPU去执行的,而是放在我们的DISK,我们的硬盘上面的。然后由我们的BIOS Basic Input Output System提供相应的支持,它能够在我们计算机插电后,就能够开始检查各种各样的外设,然后才能加载相应的软件进行执行。

BIOS设置程序是储存在BIOS芯片中的,BIOS芯片是主板上一块长方
主板上的BIOS芯片
主板上的BIOS芯片
形或正方形芯片,只有在开机时才可以进行设置。主板上的BIOS芯片或许是主板上唯一贴有标签的芯片,一般它是一块32针的双列直插式的集成电路,上面印有"BIOS"字样。

BIOS芯片中主要存放:
●自诊断程序:通过读取CMOSRAM中的内容识别硬件配置,并对其进行自检和初始化;
● CMOS设置程序:引导过程中,用特殊热键启动,进行设置后,存入CMOS RAM中;

CMOS是Complementary Metal Oxide Semiconductor(互补金属氧化物半导体)的缩写。
它是指制造大规模集成电路芯片用的一种技术或用这种技术制造出来的芯片,是电脑主板上的一块可读写的RAM芯片。
因为可读写的特性,所以在电脑主板上用来保存BIOS设置完电脑硬件参数后的数据,这个芯片仅仅是用来存放数据的。

● 系统自举装载程序:在自检成功后将磁盘相对0道0扇区上的引导程序装入内存,让其运行以装入DOS系统;
● 主要I/O设备的驱动程序和中断服务:由于BIOS直接和系统硬件资源打交道,因此总是针对某一类型的硬件系统,而各种硬件系统又各有不同,所以存在各种不同种类的BIOS,随着硬件技术的发展,同一种BIOS也先后出现了不同的版本,新版本的BIOS比起老版本来说,功能更强。现版本它被保存在闪存中,它是非易失性的,但是当BIOS 中发现错误时,可以由操作系统进行更新。
在这里插入图片描述
在我们计算机内存里面,有一部分内存是我们BIOS已经占满的,我们BIOS第一步要做的事情就是从一个特定的地址开始执行,以x86为例,这个地址是一个固定的地址CS:IP = 0xf000:fff0. CS(段寄存器),IP(指令寄存器),我们的BIOS就从这个地址开始执行,进行一系列的工作。POST(Power On Self Test 加电自检),寻找显卡和执行BIOS。
在这里插入图片描述
但是我们的BIOS并不直接引导我们的操作系统进入内存,仍然位于我们的硬盘上,那么在硬盘的主引导区,还需要一个Bootloader。这个Bootloader可以从磁盘文件系统中把操作系统引导起来。或者说操作系统引导记录

Bootloader是在操作系统运行之前执行的一段小程序。通过这段小程序,
我们可以初始化硬件设备、建立内存空间的映射表,
从而建立适当的系统软硬件环境,为最终调用操作系统内核做好准备

Bootloader(OBR)一般在我们硬盘的第一个主引导扇区,方便BIOS很容易的找到

即我们的BIOS加载Bootloader,Bootloader(主引导记录OBR)加载OS的一个过程

操作系统如何与设备和程序进行交互

为什么我们的应用程序不能直接访问我们计算机的设备,而是需要操作系统呢?

-计算机运行时,内核(os)是被信任的第三方。安全性(应用程序是有风险的)
-只有内核可以执行特权指令。
-为了方便应用程序。

操作系统的Interface

面向外设通过中断和I/O进行处理
面向应用程序通过系统调用和异常来提供相应的功能

定义:
系统调用:(来源于应用程序)应用程序主动向操作系统发出服务请求。

异常:(来源于不良的应用程序)非法指令或其它花的处理状态(e.g.内存出错)。

中断:(来源于外设)来自不同的硬件设备的计时器和网络的中断

产生的源头:
-中断:外设(键盘/鼠标/网卡/声卡/显卡,可以产生各种事件)

-异常:应用程序意想不到的行为(e.g.异常,恶意程序,应用程序需要的资源未得到满足)

-系统调用(system call):应用程序请求操作提供服务(e.g.打开/关闭/读写文件,发送网络包)

处理时间:
-中断:异步;

-异常:同步;

-系统调用:同步或异步。

响应:
-中断:持续,对用户应用程序时透明的

-异常:杀死或者重新执行意想不到的应用程序指令

-系统调用:等待和持续

操作系统的中断,异常和系统调用

中断/异常处理机制
中断是外设的事件,异常是CPU的事件;中断/异常迫使CPU访问一些被中断和异常服务访问的功能。

中断:

  • 硬件:设置中断标记(cpu初始化)
    1.将内部/外部事件设置中断标记
    2.中断事件的ID(中断处理例程的地址)
  • 软件:操作系统
    1.保存当前处理状态
    2.中断服务程序处理
    3.清除中断标记
    4.恢复之前保存的处理状态

异常:异常编号

  • 保存现场
  • 异常处理:杀死产生异常的程序;重新执行异常指令
  • 恢复现场

系统调用(接口):

系统调用是指我们的应用程序需要操作系统的服务时,产生的便于操作系统为应用程序提供服务的接口。一条应用程序的指令便会触发系统调用。

  • 程序访问主要是通过高层次的API接口而不是直接进行系统调用。(例如windows系统提供的win32 的API。 用于POSIX-based systems的POSIX API)
  • 通常情况下,存在与每个系统调用相关的序号,系统调用接口根据这些序号来维护表的索引。
  • 系统调用接口调用内核态中预期的系统调用,并返回系统调用的状态和其它任何返回值。
  • 用户不需要知道系统调用是如何实现的,只需要获取API和了解操作新系统将什么作为返回结果。操作系统接口的细节大部分都隐藏在API中,并通过运行程序支持的库来管理。

用户态:应用程序在执行的过程中,CPU执行的特权级的状态(很低,不能访问特殊机器指令和IO)。

内核态:应用程序在执行的过程中,CPU执行的特权级的状态(高,操作系统可以执行CPU任何一条指令)。

系统调用和我们传统的函数调用是有区别的:
当我们的应用程序发出函数调用的时候,它其实是在一个栈空间内完成了这个参数的传递,和参数的返回;但是在系统调用的时候,我们的应用程序和我们的内核其实是有各自的堆栈,也就意味着当我们应用程序发出了系统调用之后,切换到内核的时候需要切换堆栈同时完成特权级从用户态向内核态的转化,这两个变化比函数调用的开销更大,但更安全和可靠。

执行中断、异常、系统调用机制可能造成的额外开销:

  • 在执行时间上超过程序调用
  • 开销包括:
    1.建立中断/异常/系统调用号与对应服务例程映射关系的初始化开销;
    2.建立内核堆栈(操作系统和应用程序的堆栈不一样);
    3.验证参数(操作系统会检查数据);
    4.内核态映射到用户态的地址空间,更新页面映射权限(内存拷贝开销);
    5.内核态独立地址空间TLB。

计算机体系结构之内存

内存的分层体系

在这里插入图片描述
从上到下我们可以看到CPU可以访问的数据包含很多,第一部分是寄存器,第二部分是cache,这两个部分都是位于我们CPU的内部的,我们的操作系统没有办法对它进行直接的管理,他们的速度很快,容量很小,能放置的数据和指令是有限的,为此我们在计算机里面还要有一块很大的存储空间,叫做主存(物理内存)来放置我们操作系统本身,或者程序运行的指令或数据,但它的容量也不一定够用,这时候我们在内存中放不进去的数据或者指令,就需要放到我们的硬盘中去。同时在我们进行数据内存管理的时候,我们计算机一旦离电,其主存中的数据就不再存在了,所有我们将一些常用的数据或程序段保留在我们的硬盘里面,当我们需要的时候,再从中读取到主存里面去。
所以通过这个层次结构,我们编程用户所希望达到的效果就是,我们的数据处理运行时间很快,我们的数据存储空间也很大。同时兼顾这两点,就需要我们操作系统进行管理

操作系统在内存管理中要完成的目标

  • 抽象:逻辑地址空间
  • 保护:独立地址空间
  • 共享:访问相同内存
  • 虚拟化:更多的地址空间

在这里插入图片描述

操作系统实现内存管理目标的手段

  • 程序重定位
  • 分段
  • 分页
  • 虚拟内存
  • 按需分页虚拟内存

地址空间与地址生成

定义

  • 物理地址空间:硬件支持的地址空间
    物理地址空间是与我们的硬件进行直接的对应的,比如我们的内存条所代表的主存,硬盘代表的存储空间
  • 逻辑地址空间:一个运行的程序所拥有的内存范围
    一个运行的程序,它所看到的内存空间,一般而言其内存空间相对简单,是一个一维的线性地址空间,有了这个一维的线性空间后,我们的应用程序很容易的进行相关的访问操作。

但是我们所有应用程序所访问的逻辑地址空间,最终都要转化为相应的物理地址空间,所以我们就需要知道,逻辑地址空间与物理地址空间之间是怎样形成映射关系的

逻辑地址的生成:
在这里插入图片描述
以c程序为例,一个c程序通过编译后可以变成我们的汇编程序,在我们c程序中,函数的位置,变量的名字就是一种逻辑地址,它是以一种人更容易理解的方式存在的。汇编程序更贴近机器语言,便于机器的理解,但是其依然是一种用符号代替变量或函数名字的一种方式,这种汇编语言经过汇编器可以转化为机器语言即.o程序,在这种机器语言的句段中我们可以看到,其将变量的名字还有函数转换成了地址,相对从一开始的连续的地址空间

应用程序的逻辑地址是如何映射到物理地址
在这里插入图片描述
CPU方面
1.运算器ALU需要在逻辑地址(提出需要)
2.内存管理单元MMU寻找在逻辑地址和物理地址之间的映射,MMU没有就去内存中找(查找)
3. 控制器从总线发送在物理地址的内存内容的请求(找对应物理地址)

内存方面
内存发送物理地址内存内容给CPU(找到地址给CPU)

操作系统方面
建立逻辑地址和物理地址之间的映射(确保程序不相互干扰)

地址检测:
在这里插入图片描述

操作系统的内存分配

在多道程序环境下,内存如何分配至关重要。当用户程序要装入内存创建进程时,需向操作系统提出申请,操作系统按一定策略分配存储空间。操作系统必须随时掌握内存空间的使用情况,譬如可以设计一张内存分配表记录各内存区域的分配情况。当用户提出存储申请时,操作系统按一定策略从表中选出符合申请者要求的空闲区进行分配,并修改表内有关项,称为内存的分配;

存储(内存 )管理的主要方式:
存储管理方式可以分为连续分配方式和离散分配方式两大类。其中,连续分配方式可以分为单一连续分配方式和分区分配方式,分区分配方式又可分为固定分区和可变分区两种方式。离散分配方式有分页存储器管理方式、分段存储器管理方式和段页式存储管理方式。此外,存储管理方式还包括覆盖技术、交换技术和虚拟存储器管理,虚拟存储器管理包括请求分页存储管理方式和请求分段存储管理方式
在这里插入图片描述

连续内存分配:

单一连续分配:

单一连续分配是最简单的一种存储管理方式,但只能用于单用户、单任务的操作系统中。采用这种存储管理方式时,内存的用户区一次只分配给一个用户程序使用。这种管理方式的分配、回收算法非常简单。一般情况下,一个程序实际只占用该区的一部分,剩余的部分只能空闲未被利用,所以这种存储管理方式内存的利用率很低。

在单一连续分配中,存储保护机构是设置基址寄存器和界限地址寄存器。
在这里插入图片描述
分区分配:
分区分配的存储管理是为了适应多道程序设计技术而产生的最简单的存储管理。它把内存划分成若干个连续的区域,每个用户程序占有一个。

1.固定分区分配:
固定分区方法是指系统预先把内存中的用户区分成若干个连续的区域,每个区域称为一个“分区”。各分区的大小可以相同,也可以不相同,程序装入时,根据它对内存大小的需求量,系统将按照一定的策略把能满足它要求的一个分区分配给该程序。采用固定分区存储管理时,进入内存的每一个程序都占据一个连续的分区。

为了能对内存各分区的划分和使用情况加以有效地管理,系统设有一张固定分区分配表,固定分区分配表的内容包括分区号、起始地址、长度、占用标志等。“占用标志”记录分区的使用状态

在这里插入图片描述
在固定分区中,有两种保护机构:设置上、下限寄存器或设置基址、长度寄存器。

2.可变(动态)分区分配:
可变分区管理与固定分区的主要区别是系统并不预先划分内存空间,而是在程序装入时根据程序的实际需要动态地划分内存空间。若无空闲的存储空间或无足够大的空闲存储空间供分配时,则拒绝为该程序分配内存。

为了实现分区分配,系统中必须配置相应的数据结构,用来记录内存的使用情况,为内存的分配、回收提供依据。常用的数据结构有已分分区表和空闲分区表

在这里插入图片描述
动态分区分配算法:
问题:我们操作系统在什么时候提供这样的一个连续空间的分配?
1.操作系统把我们的应用程序从硬盘中加载到内存中去,那么就需要给我们的应用程序分配连续的内存空间,以至于程序能够顺利的运行起来。
2.应用程序在运行的时候,需要访问我们的一些数据,这时候需要我们OS给这些数据提供内存空间

为此操作系统需要管理我们整个的空闲和非空闲的内存空间,所以就需要一些内存分配算法来完成这些事情。

基于顺序搜索的动态分区算法(传统算法):

1.首次适配(first fit FF)算法:
分配n字节,从低地址开始找,碰到的第一个空间比n大的空闲块就使用它。
在这里插入图片描述
算法需求:

  • 需要存在一个按地址排序的空闲块列表
  • 分配需要找一个合适的分区
  • 重分配需要检查(回收操作),看看自由分区能不能与相邻的空闲分区合并形成更大的空闲块(若有)

该算法倾向于优先利用内存中低址部分的空闲分区,在高址部分的空闲分区很少被利用,从而保留了高址部分的大空闲区。这为以后到达的大程序分配大的内存空间创造了条件。其缺点是低址部分不断被划分,致使留下许多难以利用的、很小的空闲分区,称为内存碎片。其每次查找都从低址部分开始,这无疑会增加查找可用空闲分区的开销。

2.最佳适配算法(best fit BF)
分配n字节,使用最小的可用空闲块,以致块的尺寸比n大。每次为程序分配内存时,总是把既能满足要求、又是最小的空闲分区分配给程序,避免“大材小用”。
在这里插入图片描述
算法条件:

  • 按尺寸排列的空闲列表
  • 分配需要寻找一个合适的分区
  • 重分配需要搜索和合并于相邻的空闲分区(若有)

最佳适应算法似乎是最佳的,其实却不一定。因为每次分配后所切割下的剩余部分总是最小的,最容易形成内存碎片。

  • 优点:大部分分配是小尺寸时很有效;简单
  • 缺点:外部碎片;重分配慢;易产生很多没用的微小碎片。

3.最差适配(worst fit WF)算法:
分配n字节,使用最大的可用空闲块,以致块的尺寸比n大。
每次为程序分配内存时,总是找到一个满足程序长度要求的最大空闲分区进行分配,以便使剩下的空闲区不至于太小而形成内存碎片
在这里插入图片描述
算法条件:

  • 按尺寸排列的空闲列表
  • 分配很快(获得最大的分区)
  • 重分配需要合并于相邻的空闲分区,若有,然后调整空闲块列表

这种算法适合于中、小程序运行,但对大程序的运行来讲是不利的。

  • 优点:假如分配时是中等尺寸效果最好
  • 缺点:重分配慢;外部碎片;易于破碎大的空闲块以至大分区不能被分割

内存碎片问题:

  • 空闲内存不能被利用
    外部碎片:在分配单元间的未使用内存
    还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域。
    内部碎片:在分配单元中的未使用内存
    是已经被分配出去(能明确指出属于哪个进程)却不能被利用的内存空间。
    在这里插入图片描述

碎片状态:
1、外碎片:这些存储块的总和可以满足当前申请的长度要求,但是由于它们的地址不连续或其他原因,使得系统无法满足当前申请。

2、内碎片:占有这些区域或页面的进程并不使用这个存储块。而在进程占有这块存储块时,系统无法利用它。直到进程释放它,或进程结束时,系统才有可能利用这个存储块。

前面我们以及可以看到,无论我们采用何种内存分配方式,都不可避免的会产生一些碎片,那我们如何处理这些碎片,或者说,在事后弥补一下,让这些碎片尽可能的少一些。让这些内存空间尽量大尽量连续,便于后续的内存空间的分配。那么就有了下面的两种算法

压缩式与交换式碎片整理:

1.压缩式碎片整理(紧凑):
将内存中的所有进程进行移动,使它们相邻接。原来分散的多个小分区便拼接成一个大分区,从而就可以把程序装入运行。这种通过移动,把多个分散的小分区拼接成大分区
在这里插入图片描述
紧凑的开销是很大的,因为它不仅要修改被移动进程的地址信息,而且要复制进程空间,所以如不必要,尽量不做紧凑。通常仅在系统接收到程序所发出的申请命令,且每个空闲区域单独均不能满足,但所有空闲区域之和能够满足请求时才进行一次紧凑。由于经过紧凑后,进程在内存中的位置发生了变化,若不对程序和数据的地址进行修改(变换),则进程将无法执行。为使之能够执行,必须进行重定位,即用新的开始地址替换重定位寄存器中原来的地址。

2.交换式碎片整理:
交换(又称对换)就是系统根据需要把内存中暂时不运行的某个(或某些)进程部分或全部移到外存,以便腾出足够的内存空间,再把外存中的某个(或某些)已具备运行条件的程序移到相应的内存区,创建进程,并使其投入运行。
在这里插入图片描述
交换的时机通常在以下情况发生:
(1)进程用完时间片或等待输入/输出。

(2)进程要求扩充存储而得不到满足时。

非连续(离散)内存分配:

问题:为什么要用非连续内存分配?
在连续分配方式中,会形成很多碎片,虽可通过紧凑方法将许多碎片拼接成可用的大块空间,但必须为之付出很大的开销,如果允许将一个进程直接分散的装入许多不相邻接的分区中,便可充分的利用内存空间,而无需进行紧凑,所以便有了我们非连续的内存分配方式。

非连续内存分配的优点:

  • 分配给一个程序的物理内存是非连续的
  • 更好的内存利用和管理
  • 允许共享代码和数据(共享库等)
  • 支持动态加载和动态链接

非连续内存分配的缺点:

  • 如何建立虚拟地址和物理地址之间的转换
  • 软件方案(开销大)

两种方案:

  • 分页
  • 分段
分段管理(更好的分离和共享):

分段存储管理方式要求每个程序的地址空间按照自身的逻辑关系划分成若干段,比如主程序段、子程序段、数据段、堆栈段等,每个段都有自己的名字。为了简单,通常可用一个段号来代替段名,每个段都从0开始独立编址,段内地址连续。段的长度由相应的逻辑信息组的长度决定,因而各段的长度不等。分配内存时,为每个段分配一连续的存储空间,段间地址空间可以不连续

关注的两个问题:
分段的地址空间:
在这里插入图片描述
逻辑上是连续的,物理上是分散的。

在这里插入图片描述
通过我们的段映射机制,可以将我们的不同的程序段映射到不同的内存空间

分段寻址方案:

段表
在这里插入图片描述
在分段存储管理系统中,逻辑地址分为段号和段内地址两部分
在这里插入图片描述
实现方案:

在进行地址变换时,首先比较逻辑地址中的段号和段表寄存器中的段表长度,如果段号大于或等于段表长度,则访问越界,产生一越界中断,由系统处理。如果没有越界,则用段号和段表寄存器中的段表始地址检索段表,按照始址和段号找到该逻辑地址所在的段在段表中的位置,从中读出该段的始址,然后比较逻辑地址中的段内地址和段长,如果段内地址大于或等于段长,则越界。如果没有越界,则用该段的始址加上段内地址得到要访问的物理地址
在这里插入图片描述

分页管理:

分页和分段的主要区别:

  • 页是信息的物理单位,分页是为了系统管理内存的方便而进行的,故对用户而言,分页是不可见的,是透明的;段是信息的逻辑单位,分段是程序逻辑上的要求,对用户而言,分段是可见的。
  • 页的大小是固定的,由系统决定;段的大小是不固定的,由用户程序本身决定。
  • 从用户角度看,分页的地址空间是一维的,而段的地址空间是二维的。

分页的地址空间:

  • 划分物理内存至固定大小的帧:大小是2的幂,e.g.512,4096,8192
  • 划分逻辑地址空间至相同大小的页:大小是2的幂,e.g.512,4096,8192
  • 建立方案:转换逻辑地址为物理地址(pages to frames)
    1.页表Page Table
    2.MMU/TLB(快表)

物理地址页帧:

页帧 : 物理内存被分割为大小相等的帧(物理地址部分)

  • 一个内存的物理地址是一个二元组(f,o)
  • f:帧号(它是F位的,因此意味着一共2F个帧);
  • o:帧内偏移(它是S位的,因此意味着每帧有2^S 字节);
  • 物理地址=2^S x f + o。

在这里插入图片描述
计算实例:
在这里插入图片描述
16-bit的空间,页帧偏移是9-bit,帧号是16-9=7-bit位,物理内存地址(3,6),帧号是3,说明一共能有2^7个帧,这个帧是其中的第3个;
帧内偏移是6,他是9位的,说明一个帧里可以有2^9个字节
F=7, f=3 ,o=6,S=9
因此,它的物理地址是3 * 2^9 + 6。

逻辑地址页:
在这里插入图片描述

页表:
在进程逻辑地址空间内的所有页,依次在页表中占据一个表项,其中记录了相应页在内存中对应的物理块号(帧号)

在配置了页表后,进程执行时,通过查找页表找到每页在内存中的物理块号。可见,页表的作用是实现从页号到物理块号的地址映射。系统在内存空间设置一片区域作为页表区,系统为每个进程提供一个页表。进程页表的起始地址存放在进程PCB中。
在这里插入图片描述
分页的寻址方式:
系统设置了一个页表寄存器(Page-Table Register,PTR),其中存放页表在内存的始址和页表的长度。进程未执行时,页表的始址和长度存放在对应进程的PCB中。当调度程序调度到某进程时,才将它们装入到页表寄存器中

在执行检索之前,先将页号与页表寄存器中的页表长度进行比较,如果页号大于或等于页表长度,则表示本次所访问的地址已超越进程的地址空间。于是,这一错误将被系统发现并产生一地址越界中断。若没有出现越界错误,则将页表始址与页号和页表项长度的乘积相加,便得到该表项在页表中的位置,于是可从中得到该页的物理块号,将之装入物理地址寄存器中,与此同时,再将逻辑地址寄存器中的页内地址直接送入物理地址寄存器的块内地址字段中。这样便完成了从逻辑地址到物理地址的转换
在这里插入图片描述

分页机制的性能问题:
空间代价和时间代价:

  1. 访问一个内存单元需要2次内存访问
  • 一次用于获取页表项
  • 一次用于访问数据
  1. 页表可能非常大
    64位机器,如果一页是1024KB,那么页表是多大?
    假如页号是n位的,那么页表的长度等于2^ n,一页是1024KB,所以页内偏移是10位,一个逻辑地址的长度等于计算机位数,也就是64位,因此剩下的54位是留给页号的;因此页表的长度是2^54,明显CPU装不下。

一个程序一个页表,n个程序n个页表,就更大了。

CPU装不下,只能装在内存里;如果这样,需要访问2次内存,一次访问页表,一次访问程序。

解决办法:

  • 缓存caching
  • 间接访问indirecion

转换后备缓冲区/快表TLB:
TLB实际上是CPU的MMU内存管理单元保存的一段缓存,这段缓存保存的内容是 页表 的一部分,是经常访问到的那部分页表,其余不常用的页表内容保存在内存中。

利用快表进行读/写操作的过程是,首先按逻辑地址中的页号先查快表,若该页在快表中,则立即能得到相应的物理块号并与页内地址形成物理地址;若该页不在快表中,则再查内存中的页表找到相应的块号,形成物理地址,同时将该页的对应项写入快表。若快表已满,则按照一定策略淘汰一个旧项。最简单的策略是“先进先出”原则,即淘汰最先进入快表的那一项。

在这里插入图片描述

两级和多级页表:

现代的大多数计算机系统都支持非常大的逻辑地址空间,页表就变得非常大,要为它分配一大段连续的内存空间将变得十分困难。
例如,对于一个具有32位逻辑地址空间的分页系统(32位的计算机对应的虚拟地址空间大小就是2^32 字节),规定页面大小为4KB=2^12B,页表项是4B,由已知条件求得页面数目(页号) =2^32B / 2^12 B=2^20页,同时得出页号地址是20位。每个进程中页表的页表项有1M个,故每个进程仅页表就需要占用4MB的内存空间,而且还要求是连续的。显然这是不现实的,可以采用两个办法来解决这个问题:

(1)采用离散分配方式来解决难以找到一块连续的内存空间问题。
(2)只将当前需要的部分页表项调入内存,其余的页表项仍驻留在磁盘上,需要时再调入。

两级页表:
采用离散分配方式需将页表进行分页,并将各个页表页分别存放到不同的内存块中。此时,必须为离散分配的页表再建立一张页表,称为外层页表,用来记录存放各页表页的内存块号,从而形成了两级页表。
在这里插入图片描述
两级页表的地址变换:
在这里插入图片描述
对页表进行离散存储的方法虽然解决了页表需要连续内存空间的问题,但并未解决用较小的内存去存放大页表的问题

如果外层页表仍十分庞大,则可以将它再进行分页并离散地存储到内存中,然后再通过一张第二级的外层页表来记录存放各外层页表页分页的内存块号,这样就形成了三级页表,并可进一步形成更多级的页表。

在这里插入图片描述

段页式存储管理:

分页存储管理方式提高了内存的利用率,分段存储管理方式方便了用户的使用。结合两者的优点,将分页存储管理方式和分段存储管理方式组合在一起,形成了段页式存储管理方式。

基本思想:
内存分成大小相同的块,每个程序地址空间按照逻辑关系分成若干段,并为每个段赋予一个段名,每段可以独立从0编址,每段按内存块大小分成页,每段分配与其页数相同的内存块,内存块可以连续也可以不连续。系统为每段建立页表记录每页对应的块,同时还为该程序建立段表记录每段对应的页表(段表以及段内页表中的状态位为实现虚拟存储而设置)
在这里插入图片描述
地址结构:
在这里插入图片描述
为了访问段页式的地址空间,逻辑地址由3部分组成:段号s、段内页号p和页内地址d

地址变换:
在这里插入图片描述
为了实现地址变换,配置一段表寄存器来存放段表的始址和段长。地址变换时,首先利用段号和段长进行比较,如果段号小于段长,则没有越界,于是利用段表寄存器中的段表始址和段号求出该段的段表项在段表中的位置,从中得到该段的页表始址,并利用逻辑地址中的段内页号得到该页对应的页表项的位置,从中读出该页所对应的物理块号,把物理块号和页内地址送到物理地址寄存器,构成物理地址。

虚拟存储器(虚拟内存)

无论是单一连续分配、分区分配还是分页存取管理方式和分段存储管理方式,都有一个共同的特点:需要将程序一次性装入内存。这样如果程序很大,其所要求的内存空间超过当前内存空间总和,则程序不能被一次性的装入内存,会致使程序无法执行。另外,当要运行的程序很多,而内存空间不足,则只能让一部分程序先运行,大量程序只能在外存中等待。为了解决这些内存不足的情况,可以从物理上和逻辑上两方面扩充内存容量。虚拟存储器就是使用虚拟技术从逻辑上对存储器进行扩充。

我们理想的存储器: 容量大,速度快,成本便宜,非易失性
现实存储器:在这里插入图片描述

在计算机系统中,尤其是在多道程序运行的环境中,可能会出现内存不够用的情况,怎么办?

  • 如果程序太大,超过了内存的容量,可以采用 手动的覆盖(overlay) 技术,只把需要的指令和数据保存在内存中
  • 如果是程序太多,超过了内存的容量,可以采用 自动的交换(swapping) 技术,把暂时不能执行的程序送到外存中
  • 如果想在有限容量的内存中,以更小的页粒度为单位装入更多更大的程序,可以采用 自动的虚拟存储技术 。

覆盖技术:

所谓覆盖是指同一内存区可以被不同的程序段重复使用。通常一个程序由若干个功能上相互独立的程序段组成,程序在一次运行时,也只用到其中的几段,利用这样一个事实,就可以让那些不会同时执行的程序段共用同一个内存区。把可以相互覆盖的程序段称为覆盖,而把可共享的内存区称为覆盖区。把程序执行时并不要求同时装入内存的覆盖组成一组,称为覆盖段,并分配同一个内存区。覆盖段与覆盖区一一对应。

覆盖部分自身逻辑结构:
在这里插入图片描述

  • 必要部分(常用功能)的代码和数据常驻内存
  • 可选部分(不常用功能)在其它程序模块中实现,平时存放在外存中,在需要时才装入内存。
  • 不存在调用关系的模块不必同时装入内存,从而可以相互覆盖,即这些模块共用一个分区。

缺点:

  • 由程序员来把一个大的程序划分为若干个小的功能模块,并确定各个模块之间的覆盖关系,费时费力,增加了编程的复杂度。
  • 覆盖模块从外存装入内存,是以时间换空间。

交换技术:

可将暂时不能运行的程序送到外存,从而获得空闲内存空间。
操作系统把一个进程的整个地址空间的内容保存到外存中(换出swap out),而将将外存中的某个进程的地址空间读入到内存中(换入swap in)。换入换出内容大小为整个程序的地址空间。
在这里插入图片描述
交换实现的要求:

  • 交换时机的确定:只有当内存空间不够或有不够的危险时换出
  • 交换区的大小:必须足够大以存放所有用户进程的所有内存映像的拷贝,必须能对这些内存映像进行直接存取
  • 程序换入时的重定位:因为换出换入后的内存位置不一定相同,所以最好采用动态地址映射的方法

虚拟存储技术:

为什么引入虚拟存储技术?

  • 解决覆盖技术给程序员负担大和交换技术处理器开销大的问题。
  • 像覆盖技术一样,不是把程序的所有内容都放在内存中,因而能够运行比当前的空闲内存空间还要大的程序。但做得更好,能由操作系统自动完成,无需程序员介入
  • 能像交换技术那样,能够实现进程在内存和外存之间的交换,因而获得更多的空闲内存空间。但能做得更好,只对进程的部分内容在内存和外存之间进行交换。

局部性原理:

程序在执行过程中呈现局部性原理
在几乎所有程序的执行中,一段时间内往往呈现出高度的局部性,即程序对内存的访问是不均匀的,表现在时间与空间两方面。

(1)时间局部性。一条指令被执行后,那么它可能很快会再次被执行。程序设计中经常使用的循环、子程序、堆栈、计数或累计变量等程序结构都反映了时间局部性。

(2)空间局部性。若某一存储单元被访问,那么与该存储单元相邻的单元可能也会很快被访问。程序代码的顺序执行,对线性数据结构的访问或处理,以及程序中往往把常用变量存放在一起等都反映出空间局部性。

换句话说,CPU总是集中地访问程序中的某一个部分而不是随机地对程序所有部分平均地访问。局部性原理使得虚拟存储技术的实现成为可能。

我们在平时程序运行的时候会看到很多情况:

(1)程序中的某些部分在程序整个运行期间可能根本就不用。像出错处理程序,只有在数据或计算处理出错时才会运行,而在程序的正常运行情况下,没有必要把它调入内存。
(2)许多表格占用固定数量的内存空间,而实际上只用到其中的一部分。(3)许多程序段是顺序执行的,还有一些程序段是互斥执行的,在这些运行活动中只可能用到其中之一,它们并没有必要同时驻留在内存。
(4)在程序的一次运行过程中,有些程序段被执行之后,将从某个时刻起不再用到

程序局部性原理和上述事实说明没有必要一次性把整个程序全部装入内存后再开始运行,在程序执行过程中其某些部分也没有必要从开始到结束一直都驻留在内存,而且程序在内存空间中没有必要完全连续存放,只要局部连续便可。

虚拟存储器定义:
所谓虚拟存储器是指仅把程序的一部分装入内存便可运行程序的存储器系统。具体地说,虚拟存储器是指具有请求调入功能和置换功能,能从逻辑上对内存容量进行扩充的一种存储器系统。实际上,用户所看到的大容量只是一种感觉,是虚的,故称之为虚拟存储器。虚拟存储器逻辑容量由内存和外存容量之和所决定,其运行速度接近于内存速度,成本又接近于外存

分页虚拟存储管理:

基本原理:

分页虚拟存储管理方式是在分页系统的基础上增加了请求调页功能和页面置换功能所形成的虚拟存储器系统。在进程装入内存时,并不是装入全部页面,而是装入若干页(一个或零个页面),之后根据进程运行的需要,动态装入其他页面;当内存空间已满,而又需要装入新的页面时,则根据某种算法淘汰某个页面,以便腾出空间,装入新的页面。

页表表项:
在这里插入图片描述
在这里插入图片描述
缺页中断:
在分页虚拟存储管理系统中,每当要访问的页面不在内存时,便产生一个缺页中断,请求操作系统把所缺页面调入内存。缺页中断作为中断,它同样需要经历诸如保护CPU现场环境、分析中断原因、转入缺页中断处理程序进行处理、恢复CPU环境等几个步骤。但缺页中断又是一种特殊的中断,它与一般的中断相比有着明显的区别:

(1)在指令执行期间产生和处理中断信号。通常,都是在一条指令执行完后去检查是否有中断产生。若有,便去响应处理中断;否则,继续执行下一条指令。然而,缺页中断是在指令执行期间,发现所要访问的指令或数据不在内存时产生和处理的。

(2)一条指令在执行期间,可能产生多次缺页中断。如图6-1所示的一个例子,在执行一条copy A to B的指令时,可能要产生6次缺页中断,其中指令本身跨了两个页面,A和B分别是一个数据块,也都跨了两个页面。基于这些特征,系统中的硬件机构应能保存多次中断时的状态,并保证最后能返回到中断前产生缺页中断的指令处,继续执行。

在这里插入图片描述
页面置换算法:

功能:当缺页中断发生,需要调入新的页面而内存已满时,选择内存当中哪个物理页面被置换。

目标尽可能减少页面的换入换出次数(即缺页中断的次数)。把未来不再使用的或短期内较少使用的页面换出,通常只能在局部性原理的指导下依据过去的统计数据来进行预测。

页面锁定(frame locking):用于描述必须常驻内存的操作系统的关键部分或时间关键(time-critical)的应用进程。实现方法是,在页表中添加锁定标志位(lock bit)。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
LRU算法是较好的一个算法,但是开销太大,要求系统有较多的支持硬件。为了实现LRU,必须在内存维护一张程序所有页的链表,表中各项按访问时间先后排序,最近访问的页排在表头,最久未用的页排在表尾,这就是所谓的栈式算法。每当要置换一页时,必须对链表中的各项进行修改。若被访问的页在内存,则将其移到表头,调整相应项。若不在内存,则将新调的页放在表头,其他项依次后移,将表尾一项挤掉。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

全局页面置换算法:

工作集是指在某段时间间隔∆内进程访问页面的集合。

1.工作集模型
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
工作集页置换算法:
在这里插入图片描述
抖动问题:
虚拟存储器的实现使得只需要装入一个进程的一部分程序和数据便能运行。所以人们总是想在内存中装入更多的程序,提高多道程序的度,以便提高处理机的利用率。在开始阶段,随着进程数量的增加,处理机的利用率急剧增加,当进程的数量达到一个值Nmax时,处理机的利用率达到最大,但之后随着进程数量的继续增加,处理机的利用率反而开始缓慢下降,当超过N之后,继续增加进程的数量,处理机的利用率急剧下降趋向为零,如图6-3所示。此时系统中出现了“抖动”。
在这里插入图片描述
产生抖动的原因

产生抖动的根本原因是系统中进程的数量太多,因此分配给每个进程的物理块数量太少,使得每个进程在运行时频繁的发生缺页中断,请求操作系统把所缺页面由外存调入内存,显然这样对磁盘的访问时间也随之急剧增加。每个进程的大部分时间都用于页面的换进换出,而几乎不能再去做任何有效的工作,从而导致发生处理机利用率急剧下降,而趋于零的现象,称此时系统处于抖动状态。

预防抖动的方法:

(1)采用局部置换策略。在页面分配和置换策略中,如果采取的是可变分配方式时,为了预防抖动的产生,可采取局部置换策略。当某个进程发生缺页时,只能在分配给自己的内存空间进行置换,不允许从其他进程处获得新的物理块。这样,即使该进程发生了抖动也不会影响到其他进程的运行,不会引发其他进程出现抖动,使抖动局限于一个较小的范围内。该方法的优点是简单易行,但该方法并未消除抖动的发生,而在一些进程发生抖动的情况下,这些进程会长时间处于磁盘I/O的等待队列中,使队列的长度增加,从而延长了其他进程的缺页处理时间,使得平均缺页处理时间延长,延长了有效访问时间。

(2)利用工作集算法防止抖动。当调度程序发现处理机的利用率较低时,便从外存调一个新的程序进入内存,以提高处理机的利用率。当引入工作集算法后,在把新程序调入内存之前,必须先检查此时内存中的各个进程在内存中的驻留页面是否足够多,如果足够多,则新程序的调入不会导致缺页率的增加,此时便可以调新的程序进入内存;反之,如果此时有些进程的内存页面不足,则应该首先为那些进程分配新的物理块以降低其缺页率,而不是调入新的程序。

(3)利用“L=S”准则调节缺页率。L是缺页之间的平均时间,S是平均缺页服务时间,即用于置换一个页面所需要的时间。如果L远大于S,说明很少发生缺页,处理机和磁盘的能力尚未得到充分利用;如果L比S要小,说明频繁发生缺页,缺页的速度已经超出了磁盘的处理能力,可能产生了抖动。只有L和S接近时,处理机和磁盘的都可达到它们的最大利用率。理论和实践证明:利用“L=S”准则,对于调节缺页率十分有效。

(4)挂起某些进程。当多道程序的度偏高,出现处理机利用下降时,为了防止抖动的产生可以挂起一个或几个进程,腾出内存空间供缺页率较高的进程使用,从而达到预防或消除抖动的目的。被挂起进程的选择策略有多种,如选择优先权最低的进程、缺页进程、最近激活的进程、驻留集最小的进程、驻留集最大的进程等。

进程和线程

在这里插入图片描述

1.进程:

  • 进程的定义:
    在多道程序环境下,程序的执行属于并发执行,此时他们将失去封闭性,并具有间断性,以及其运行结果不可再现性的特征。由此,决定了通常的程序是不能参加并发执行的,否则,程序的运行也就失去了意义,为了能够使程序并发执行,并可以对并发执行的程序加以描述和控制,引入进程的概念。

程序段+相关的数据段+PCB=进程实体(进程映像)

  • 进程与程序的联系:
    程序是产生进程的基础
    程序的每次运行构成不同的进程
    进程是程序功能的体现
    通过多次执行,一个程序可对应多个进程;通过调用关系,一个进程可包括多个程序。

  • 进程与程序的区别:
    进程是动态的,程序是静态的:程序是有序代码的集合;进程是程序的执行,进程有核心态/用户态
    进程是暂时的,程序是永久的:进程是一个状态变化的过程,程序可长久保存
    进程与程序的组成不同:进程的组成包括程序,数据和进程控制块(进程的状态信息)

  • 进程的特点:
    动态性:可动态地创建,结束进程
    并发性:进程可以被独立调度并占用处理机运行
    独立性:不同进程的工作不互相影响
    制约性:因访问共享数据/资源或进程间同步而产生制约

程序 = 算法 + 数据结构
进程控制块(process control block, PCB): 描述进程的数据结构,操作系统管理控制进程运行所用的信息集合。
操作系统为每个进程都维护了一个PCB,用来保存与该进程有关的各种状态信息,PCB是进程存在的唯一标志。

  • 进程控制块PCB:
    PCB包含:进程标识信息;处理机状态信息保存区,保存进程的运行现场信息;进程的控制信息。

进程标识信息:本进程的标识,本进程的产生者标识(父进程标识);用户标识

处理机状态信息保存区

  • 用户可见寄存器,用户程序可以使用的数据,地址等寄存器
  • 控制和状态寄存器,如程序寄存器(PC),程序状态字(PSW)
  • 栈指针,过程调用/系统调用/中断处理和返回时需要用到它。

进程的控制信息

调度和状态信息:用于操作系统调度进程并占用处理机使用;
进程间通信信息:为支持进程间的与通信相关的各种标识,信号,信件等,这些信息存在接收方的PCB中;
存储管理信息:包含有指向本进程映像存储空间的数据结构;
进程所用资源:说明由进程打开,使用的系统资源,如打开的文件等;
有关数据结构等连接信息:进程可以连接到一个进程队列中,或连接到相关的其它进程的PCB。

PCB的组织方式:
在这里插入图片描述

进程的生命周期:

进程创建-进程运行-进程等待-进程唤醒-进程结束

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
进程的基本状态:

(1)就绪状态。当进程已分配到除处理机以外的所有必要的资源后,只要能再获得处理机便可立即执行,这时的状态称为就绪状态。在一个系统中,可以有多个进程同时处于就绪状态,通常把这些进程排成一个或多个队列,称这些队列为就绪队列。

(2)执行状态。执行状态指进程已获得处理机,其程序正在执行。在单处理机系统中,只能有一个进程处于执行状态。在多处理机系统中,则可能有多个进程处于执行状态。

(3)阻塞状态。进程因发生某种事件(例如I/O请求、申请缓冲空间等)而暂停执行时的状态,亦即进程的执行受到阻塞,故称这种状态为阻塞状态,有时也称“等待”状态或“睡眠”状态。通常将处于阻塞状态的进程排成一个队列,称为阻塞队列。在有的系统中,按阻塞的原因不同而将处于阻塞状态的进程排成多个队列。

3种基本状态的转化:
在这里插入图片描述
进程的状态转化:
在这里插入图片描述
运行状态(running):一个进程正在处理机上运行时
就绪状态(ready):一个进程获得了除处理机之外的一切所需资源,一旦得到处理机即可运行
等待状态(或阻塞状态blocked):一个进程正在等待某一事件而暂停运行时的状态,如等待资源,等待I/O完成
创建状态(new):一个进程正在被创建,还没被转到就绪状态之前的状态。
结束状态(exit):一个进程正在从系统中消失时的状态,这是因为进程结束或由于其它原因所导致。

进程挂起:

进程再挂起状态的时候,意味着进程没有占据内存空间,处在挂起状态的进程映射在磁盘上。

挂起状态:

阻塞挂起状态(blocked-suspend):进程在外存并等待某事件的出现

就绪挂起状态(ready-suspend):进程在外存,但只要进入内存,即可运行

在这里插入图片描述
在这里插入图片描述
具有挂起状态的进程变化:
在这里插入图片描述

问题:OS怎么通过PCB和定义的进程状态来管理PCB帮助完成进程的调度过程?

用进程的观点来看待OS,OS包括 用户进程,磁盘管理进程,终端进程等;
在这里插入图片描述
在这里插入图片描述

2.线程

如果说,在操作系统中引入进程的目的是使多个程序并发执行以改善资源利用率及提高系统的吞吐量;那么,在操作系统中再引入线程,则是为了减少程序并发执行时所付出的时空开销,使操作系统具有更好的并发性。

由之前进程的特点可知:进程是一个可拥有资源的独立单位,进程同时又是一个可以独立调度和分派的基本单位

为使程序能并发执行,系统还必须进行以下的一系列操作:(1)创建进程。系统在创建进程时,必须为之分配其所必需的、除处理机以外的所有资源,如内存空间、I/O设备以及建立相应的PCB。(2)撤销进程。系统在撤销进程时,必须先对资源进行回收操作,然后再撤销PCB。(3)进程切换。在对进程进行切换时,由于要保留当前进程的处理机环境和设置新选中进程的处理机环境,需花费不少处理机时间。

简而言之,由于 进程是一个资源拥有者,因而在进程的创建、撤销和切换中,系统必须为之付出较大的时空开销。 也正因如此,在系统中所设置的进程数目不宜过多,进程切换的频率也不宜过高,但这也就限制了并发程度的进一步提高。

如何能使多个程序更好地并发执行,同时又尽量减少系统的开销?

可否将进程的上述两个属性分开,由操作系统分开进行处理?即对作为调度和分派的基本单位,不同时作为独立分配资源的单位,以使之轻装运行;而对拥有资源的基本单位,又不频繁地对之进行切换。正是在这种思想的指导下,产生了线程概念。

线程的定义

线程是进程的一个实体(进程当中的一条执行流程),是被系统独立调度和分派的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器、一组寄存器和栈),但它可与同属一个进程的其他线程共享进程所拥有的全部资源。

进程=资源管理+线程

线程的特点(属性):
由于线程之间的相互制约,致使线程在运行中也呈现出间断性。相应地,线程也同样有就绪、阻塞和执行3种基本状态
1.每个线程有一个唯一的标识符和一张线程描述表,

2.不同的线程可以执行相同的程序

3.同一进程中的各个线程共享该进程的内存地址空间。

4.线程是处理机的独立调度单位,多个线程是可以并发执行的。

5.一个线程被创建后便开始了它的生命周期,直至终止,

线程的优点:

  • 一个进程中可以同时存在多个线程;
  • 各个线程之间可以并发的执行;
  • 各个线程之间可以共享地址空间和文件等资源。

线程的缺点:

  • 一个线程崩溃,该进程的所有线程崩溃。

线程的实现:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

进程同步与通信

进程间的相互作用:

操作系统内部存在着许许多多的并发活动:相对独立的多个用户程序可以并发运行;操作系统本身的许多不同功能的程序可以并发执行;一个程序内部的不同程序段可以并发执行。操作系统支持这些活动是通过进程来实现的。

进程间的联系

1.资源共享关系
2.相互合作关系

临界资源:

多道程序系统中存在许多进程,它们共享各种资源,然而有很多资源一次只能供一个进程使用。一次仅允许一个进程使用的资源称为临界资源。许多物理设备都属于临界资源,如输入机、打印机、磁带机等。

各进程采取互斥的方式,实现共享的资源称作临界资源。

临界区:

在每个进程中访问临界资源的那段代码称为临界区(Critical Section)。

临界区内放的一般是被1个以上的进程或线程(以下只说进程)共用的数据

临界区内的数据一次只能同时被一个进程使用,当一个进程使用临界区内的数据时,其他需要使用临界区数据的进程进入等待状态。

操作系统需要合理的分配临界区以达到多进程的同步和互斥关系,如果协调不好,就容易使系统处于不安全状态,甚至出现死锁现象。

为实现进程互斥,可利用软件方法在系统中设置专门的同步机制来协调诸进程

但所有的同步机制都应遵循一些准则:

同步机制应遵循的准则

  • 空闲让进- >当无进程处于临界区时,相应的临界资源处于空闲状态。因而可允许一个请求进入临界区的进程立即进入自己的临界区,以有效地利用临界资源。

  • 忙则等待- >当已有进程进入自己的临界区时,意味着相应的临界资源正被访问,因而所有其他试图进入临界区的进程必须等待,以保证诸进程互斥地访问临界资源。

  • 有限等待- >对要求访问临界资源的进程,应保证该进程能在有效的时间内进入自己的临界区,以免陷入“死等”状态

  • 让权等待- >当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”。

基于软件解决方案:

假如有两个进程P1和P2,它们共享一个临界资源R。

main(){
        cobegin{
           p1;
           p2;
               }
}      

算法1:
设置一个公用整型变量turn,用于指示被允许进入临界区的进程的编号,即若turn==1,表示允许进程P1进入临界区。算法1对P1进程的描述如下:

在这里插入图片描述
该算法可确保每次只允许一个进程进入临界区。但是强制两个进程轮流地进入临界区,很容易造成资源利用不充分。例如,当进程P1退出临界区后将turn置为2,以便允许P2进入临界区。但如果进程P2暂时并未要求访问该临界资源,而P1又想再次访问该资源,但它却无法进入临界区。可见,此算法不能保证实现“空闲让进”的准则

2.算法2:
算法1的问题在于:它采取了强制的方法让P1和P2轮流访问临界资源,完全不考虑它们的实际需要。算法2的基本思想是:在每一个进程访问临界资源之前,先去查看一下临界资源是否正被访问。若正被访问,该进程需等待;否则进入自己的临界区。为此,设置一个数组,使其中每个元素的初值为0,表示所有进程都未进入临界区。若flag[0]==1时,表示进程P1正在临界区内执行;若flag[1]==1时,表示进程P2正在临界区内执行

在这里插入图片描述

3.算法3:
算法2的问题在于:当进程P1观察到进程P2的标志为0后,便将自己的标志由0改为1,这仅需一极短的时间,而正是在此期间,它仍然表现为0而被P2所观察到。为了解决这一问题,在算法3中仍然使用了数组flag[],但令flag[0]==1表示进程P1希望进入临界区,然后再去查看P2的标志。若此时flag[1]==1,则P1等待;否则,P1进入临界区;对于进程P2亦然。换言之,算法3是使要进入临界区的进程先设置其要求进入的标志,然后,再去查看其他进程的标志

在这里插入图片描述
4.算法4:
算法4是组合了算法1和算法3中的关键概念而形成的。算法4为每个进程设置了相应的标志flag[],当flag[0]== 1 (或flag[1]== 1)时,表示进程P1(或P2)要求进入临界区或正在临界区中执行。此外,还设置了一个turn变量,用于指示允许进入临界区的进程编号。进程P1为了进入临界区先置flag[0]为1,并置turn为2,表示应轮到进程P2进入临界区。接下去再判别flag[1]&&turn==2的条件是否满足。若未满足,则可进入临界区;否则等待。或者说,当flag[1] == 0或者turn ==1时,进程P1可以进入临界区。前者表示P2未要求进入临界区,后者表示仅允许P1进入临界区。

在这里插入图片描述
当进程无法进入临界区时,上述4种算法均为忙式等待

基于硬件方式的解决方案:
在这里插入图片描述

1.关中断(禁用中断):

关中断是我们实现互斥的最简单的方法之一

关中断是为了保护一些,不能中途停止执行的程序而设计的,计算机的CPU进行的是时分复用,即每个时钟周期内,CPU只能执行一条指令。在多道程序设计的环境下(就是我们通常所说的多个程序同时运行时),CPU是不断地交替地将这些程序的指令一条一条的分别执行,这样从宏观上看我们就感觉多个程序是在同时执行,但从微观上看则是CPU在不同的时间段(极短)内执行着不同程序的单条指令。而CPU在这些指令之间的切换就是通过中断来实现的。关中断就是为了让CPU在一段时间内执行同一程序的多条指令而设计的,比如在出现了非常事件后又恢复正常时,CPU就会忙于恢复非常事件出现之前计算机的工作环境(通常叫做恢复现场),在恢复现场的时候,CPU是不允许被其他的程序打扰的,此时就要启动关中断,不再相应其他的请求。当现场恢复完毕后,CPU就启动开中断,其他等待着的程序的指令就开始被CPU执行,计算机恢复正常。

关中断的缺点:我们的中断机制最主要是为了我们计算机和我们相应的外设进行交互而用的,如果在接受某些外设响应的时候,禁中断,是会非常影响我们系统的效率的;严重限制我们处理器交叉执行的能力;关中断也不适应与多CPU系统

2.利用Test-and-Set指令实现互斥:

在许多计算机中都有这样的指令,不同计算机的相应指令的功能是相同的
在这里插入图片描述
lock有两种状态:当lock == 0时,表示该资源空闲;当lock==1时,表示该资源正在被使用。

为了实现诸进程对临界资源的互斥访问,可为每个临界资源设置一个全局变量lock并赋予其初值为0,表示资源空闲。用TS指令将变量lock的状态记录于变量TS中,并将1赋予lock,这等效于关闭了临界区,使任何进程都不能进入临界区
在这里插入图片描述
程序中的“while(TS(lock))do no-op;”语句用于检查TS指令执行后的TS状态。若为0表示资源空闲,进程可进入临界区;否则,不断测试执行TS指令后的TS变量值,直至其为0。当进程退出临界区时,设置变量lock为0,以允许其他进程进入临界区

在这里插入图片描述

信号量机制:
在这里插入图片描述
在这里插入图片描述

信号量的使用:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
同步:
在这里插入图片描述

一般/计数信号量:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

信号量实现:
在这里插入图片描述

在这里插入图片描述

处理机调度与死锁

在多道程序设计环境下,内存中存在多个进程,其数目往往多于处理机数目,这就要求,系统能按照某种算法,动态的将处理机分配给处于就绪状态的一个进程,使之执行,分配处理机的任务是由处理机调度程序完成的。对于大型系统运行时的性能,如系统吞吐量,资源利用率,作业周转时间或响应的及时性等,在很大程度上都取决于处理机调度性能的好坏,因而,处理机调度便成为OS中很重要的一部分

处理机调度: 从就绪队列中挑选下一个占用cpu运行的进程
多cpu:从多个可用cpu中挑选就绪进程可用的cpu资源

调度程序: 挑选就绪进程的内核函数

处理机调度的层次:

  • 高级调度:高级调度又称为作业调度或宏观调度。其主要功能是根据一定的算法,从输入的一批任务(作业)中选出若干个作业(从磁盘的作业后备队列中选择作业调入内存),分配必要的资源并建立与作业相对应的进程,如内存、外设等,为它建立相应的用户作业进程和为其服务的系统进程(如输入/输出进程),最后把它们的程序和数据调入内存,等待进程调度程序对其执行调度,并在作业完成后作善后处理工作。
  • 中级调度:中级调度又称为中程调度,引入中级调度的主要目的是为了提高内存的利用率和系统的吞吐量。内存中不能有太多的进程,把进程从内存移到外存,当内存有足够空间时,再将合适的进程换入内存,等待进程调度。中级调度实际上就是存储器管理中的对调功能。
  • 低级调度:低级调度又称为进程调度、短程调度,它决定就绪队列中的哪个进程将获得处理机,然后由分派程序执行把处理机分配给该进程的操作。

调度时机:

内核运行调度程序的条件

  • 进程从运行状态切换为等待状态
  • 进程被终结了

非抢占系统

  • 当前进程主动放弃cpu时。

可抢占系统

  • 中断请求被服务例程响应完成时
  • 当前进程被抢占
    1.进程时间片用完
    2进程从等待切换到就绪

调度策略需要满足的目标:

5个指标:
CPU使用率: CPU处于繁忙状态的时间百分比
吞吐量: 单位时间内完成的进程数量
周转时间: 进程从初始化到(包括等待)结束的总时间
等待时间: 进程在就绪队列中的总时间
响应时间: 从提交请求到产生响应所消耗的总时间

吞吐量与延时:
在这里插入图片描述

响应时间目标:
在这里插入图片描述
吞吐量目标:
在这里插入图片描述

调度算法

  • 先来先服务算法(FCFS)
  • 短进程优先算法(SPN,SJF,SRT)
  • 高响应比优先算法(HRRN)
  • 时间片轮转算法(RR)
  • 多级反馈队列算法(MFQ)
  • 公平共享调度算法(FSS)

1.先来先服务算法:

如果早就绪的进程排在就绪队列的前面,迟就绪的进程排在就绪队列的后面,那么先来先服务(FCFS: first come first service)总是把当前处于就绪队列之首的那个进程调度到运行状态。也就说,它只考虑进程进入就绪队列的先后,而不考虑它的下一个CPU周期的长短及其他因素。

算法关键:
按照进程进入就绪队列的先后顺序调度并分配处理机执行。先来先服务调度算法是一种非抢占式的算法,先进入就绪队列的进程,先分配处理机运行。一旦一个进程占有了处理机,它就一直运行下去,直到该进程完成工作或者因为等待某事件发生而不能继续运行时才释放处理机。

(1)系统只要有按FIFO规则建立的后备作业队列或就绪进程队列即可,就是一个作业控制块JCB或进程控制块PCB加入队列时加在相应队列末尾。

(2)调度退出队列时从相应队列首开始顺序扫描,将相关的JCB或PCB调度移出相应队列

算法优缺点:
优点: 简单
缺点:

  • 平均等待时间波动较大(短进程可能排在长进程后边)
  • I/O资源和CPU的资源利用率较低(CPU密集型进程会导致I/O设备空闲,I/O密集型进程也等待)

2.短进程优先算法:
选择就绪队列中执行时间最短的进程占用CPU进入运行状态,通常后来的短作业不抢先正在执行的作业。
是对FCFS算法的改进,其目标是减少平均周转时间。
(1) 优点:
比FCFS改善平均周转时间和平均带权周转时间,缩短作业的等待时间;

提高系统的吞吐量;
(2) 缺点:
对长作业非常不利,可能长时间得不到执行,造成饥饿;

未能依据作业的紧迫程度来划分执行的优先级;

难以准确估计作业(进程)的执行时间,从而影响调度性能

SJF的变型
“最短剩余时间优先”SRT(Shortest Remaining Time)(允许比当前进程剩余时间更短的进程来抢占)

“最高响应比优先”HRRN(Highest Response Ratio Next)(响应比R = (等待时间 + 要求执行时间) / 要求执行时间,是FCFS和SJF的折衷)

3.时间片轮转算法
将系统中所有的就绪进程按照FCFS原则,排成一个队列。
每次调度时将CPU分派给队首进程,让其执行一个时间片。时间片的长度从几个ms到几百ms。
在一个时间片结束时,发生时钟中断。
调度程序据此暂停当前进程的执行,将其送到就绪队列的末尾,并通过上下文切换执行当前的队首进程。
进程可以未使用完一个时间片,就出让CPU(如阻塞/时钟中断)。

时间片为20的RR算法实例:
在这里插入图片描述
时间片长度:
在这里插入图片描述

4.多级反馈队列算法:
多级反馈队列算法(Round Robin with Multiple Feedback)是轮转算法和优先级算法的综合和发展。
设置多个就绪队列,分别赋予不同的优先级,如逐级降低,队列1的优先级最高。每个队列执行时间片的长度也不同,规定优先级越低则时间片越长,如逐级加倍。
新进程进入内存后,先投入队列1的末尾,按FCFS算法调度;若按队列1一个时间片未能执行完,则降低投入到队列2的末尾,同样按FCFS算法调度;如此下去,降低到最后的队列,则按“时间片轮转”算法调度直到完成。
仅当较高优先级的队列为空,才调度较低优先级的队列中的进程执行。如果进程执行时有新进程进入较高优先级的队列,则抢先执行新进程,并把被抢先的进程投入原队列的末尾。

优点
为提高系统吞吐量和缩短平均周转时间而照顾短进程。

为获得较好的I/O设备利用率和缩短响应时间而照顾I/O型进程。

不必估计进程的执行时间,动态调节

算法注意:
I/O型进程:让其进入最高优先级队列,以及时响应I/O交互。通常执行一个小时间片,要求可处理完一次I/O请求的数据,然后转入到阻塞队列。

计算型进程:每次都执行完时间片,进入更低级队列。最终采用最大时间片来执行,减少调度次数。

I/O次数不多,而主要是CPU处理的进程。在I/O完成后,放回优先I/O请求时离开的队列,以免每次都回到最高优先级队列后再逐次下降。

为适应一个进程在不同时间段的运行特点,I/O完成时,提高优先级;时间片用完时,降低优先级。

5.公平共享调度算法(FSS)
分配给每个进程相同的处理机时间
在这里插入图片描述
实时操作系统:
实时操作系统的定义:

  • 正确性依赖于其时间功能两方面的操作系统

实时操作系统的性能指标:

  • 时间约束的及时性
  • 速度和平均性能相对不重要

实时操作系统的特性:

  • 时间约束的可预测性

硬实时系统:
硬实时系统指系统要有确保的最坏情况下的服务时间,即对于事件的响应时间的截止期限是无论如何都必须得到满足。比如航天中的宇宙飞船的控制等就是现实中这样的系统。

软实时系统:
其他的所有有实时特性的系统都可以称之为软实时系统。如果明确地来说,软实时系统就是那些从统计的角度来说,一个任务(在下面的论述中,我们将对任务和进程不作区分)能够得到有确保的处理时间,到达系统的事件也能够在截止期限到来之前得到处理,但违反截止期限并不会带来致命的错误,像实时多媒体系统就是一种软实时系统

可调度性: 可调度性表示一个实时操作系统能够满足任务时限要求

  • 需要确定实时任务的调度顺序

分为静态调度与动态调度:

静态调度无论是单处理器调度还是分布式调度,一般是以RMS算法为基础;

RMS(单调速率调度算法)是一种静态优先级调度算法,是经典的周期性任务调度算法。 [1] RMS的基本思路是任务的优先级与它的周期表现为单调函数的关系,任务的周期越短,优先级越高;任务的周期越长,优先级越低。如果存在一种基于静态优先级的调度顺序,使得每个任务都能在其期限时间内完成,那么RMS算法总能找到这样的一种可行的统调度方案

动态调度则以EDF、LLF为主。

最早截止时间优先算法(EDF):截至时间越早的优先级越高,执行截止时间最早的任务,当一个进程可运行时,它应向系统公布截止期限要求。优先级可能需要进行调整,以便反映新可运行进程的截止期限。

最低松弛度优先算法(LLF): LLF算法根据实时任务的松弛度来确定任务的优先权,即任务的松弛度越低,其优先权越高。在实现该算法时,要求系统中有一个按松弛度排序的实时任务就绪队列。该算法通常采用抢占方式,当一个任务的最低松弛度为 0 时,它便立即抢占 CPU,以保证它的截止时间要求。
松弛度 = 任务必须完成的时间 - 任务本身运行的时间 - 当前时间

优先级反置(倒置)
基于优先级的可抢占调度算法,存在优先级倒置
在这里插入图片描述
解决方法:
(1)设置优先级上限,给临界区一个高优先级,进入临界区的进程都将获得这个高优先级,如果其他试图进入临界区的进程的优先级都低于这个高优先级,那么优先级反转就不会发生。

(2)优先级继承,当一个高优先级进程等待一个低优先级进程持有的资源时,低优先级进程将暂时获得高优先级进程的优先级别,在释放共享资源后,低优先级进程回到原来的优先级别。

(3)第三种方法就是使用中断禁止,通过禁止中断来保护临界区,采用此种策略的系统只有两种优先级:可抢占优先级和中断禁止优先级。前者为一般进程运行时的优先级,后者为运行于临界区的优先级。火星探路者正是由于在临界区中运行的气象任务被中断发生的通信任务所抢占才导致故障,如果有临界区的禁止中断保护,此一问题也不会发生

死锁:

概念:
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。

死锁的规范定义:
集合中的每一个进程都在等待只能由本集合中的其他进程才能引发的事件,那么该组进程是死锁的。

死锁产生的条件:

1)互斥条件: 指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

2)请求和保持条件: 指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

3)不剥夺条件: 指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

4)环路等待条件: 指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

资源分类:
可剥夺资源和不可剥夺资源:
系统中的资源可以分为两类,一类是可剥夺资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺。例如,优先权高的进程可以剥夺优先权低的进程的处理机。又如,内存区可由存储器管理程序,把一个进程从一个存储区移到另一个存储区,此即剥夺了该进程原来占有的存储区,甚至可将一进程从内存调到外存上,可见,CPU和主存均属于可剥夺性资源。另一类资源是不可剥夺资源,当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。

死锁处理方法:
1.死锁预防
通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或者几个,来预防发生死锁。预防死锁是一种较易实现的方法,已被广泛使用。但是由于所施加的限制条件往往太严格,可能会导致系统资源利用率和系统吞吐量降低。

2.死锁避免
系统对进程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源;如果分配后系统可能发生死锁,则不予分配,否则予以分配。这是一种保证系统不进入死锁状态的动态策略。

3.死锁检测和解除
先检测:这种方法并不须事先采取任何限制性措施,也不必检查系统是否已经进入不安全区,此方法允许系统在运行过程中发生死锁。但可通过系统所设置的检测机构,及时地检测出死锁的发生,并精确地确定与死锁有关的进程和资源。检测方法包括定时检测、效率低时检测、进程等待时检测等。
然后解除死锁:采取适当措施,从系统中将已发生的死锁清除掉。
这是与检测死锁相配套的一种措施。当检测到系统中已发生死锁时,须将进程从死锁状态中解脱出来。常用的实施方法是撤销或挂起一些进程,以便回收一些资源,再将这些资源分配给已处于阻塞状态的进程,使之转为就绪状态,以继续运行。死锁的检测和解除措施,有可能使系统获得较好的资源利用率和吞吐量,但在实现上难度也最大。

银行家算法:
银行家算法是避免死锁的一种重要方法,防止死锁的机构只能确保上述四个条件之一不出现,则系统就不会发生死锁。通过这个算法可以用来解决生活中的实际问题,如银行贷款等。

程序实现思路银行家算法顾名思义是来源于银行的借贷业务,一定数量的本金要应多个客户的借贷周转,为了防止银行家资金无法周转而倒闭,对每一笔贷款,必须考察其是否能限期归还。在操作系统中研究资源分配策略时也有类似问题,系统中有限的资源要供多个进程使用,必须保证得到的资源的进程能在有限的时间内归还资源,以供其他进程使用资源。如果资源分配不得到就会发生进程循环等待资源,则进程都无法继续执行下去的死锁现象。

把一个进程需要和已占有资源的情况记录在进程控制中,假定进程控制块PCB其中“状态”有就绪态、等待态和完成态。当进程在处于等待态时,表示系统不能满足该进程当前的资源申请。“资源需求总量”表示进程在整个执行过程中总共要申请的资源量。显然,每个进程的资源需求总量不能超过系统拥有的资源总数, 银行算法进行资源分配可以避免死锁。

文章参考:https://www.bilibili.com/video/BV1js411b7vg?from=search&seid=8131891854631041579
https://www.bilibili.com/video/BV1x7411T7mh?p=1
操作系统第四版
操作系统第三版

  • 5
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值