操作系统——呕心沥血长篇总结(王道考研)

Posted ascto

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了操作系统——呕心沥血长篇总结(王道考研)相关的知识,希望对你有一定的参考价值。

操作系统

操作系统的概念、功能和目标

定义

在这里插入图片描述

操作系统是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境,它是计算机系统中最基本的系统软件。

功能和目标

补充:进程是一个程序的执行过程。执行前需要将该程序放到内存中,才可以被CPU处理。

作为系统资源的管理者,操作系统的功能和目标

在这里插入图片描述

作为用户和计算机硬件之间的接口-操作系统的功能和目标

在这里插入图片描述

命令接口:允许用户直接使用(联机命令接口又称为交互式命令接口,脱机命令接口又称为批处理命令接口)

程序接口:允许用户通过程序间接使用(系统调用=广义指令)

GUI:现代操作系统中最流行的图形用户接口

在这里插入图片描述

作为最接近硬件的层次-操作系统的功能和目标

需要提供的功能和目标:实现对硬件机器的扩展

没有任何软件支持的计算机成为裸机,在裸机上安装的操作系统可以提供资源管理功能和方便用户的服务功能,将裸机改造成功能更强、使用更方便的机器

通常把覆盖了软件的机器成为扩充机器或虚拟机。

类比

硬件:锤子、锯子、木头

操作系统:优秀的工匠

通过锤子锯子木头和工匠打造出来房屋。

操作系统的四个特征

并发、共享、虚拟、异步

其中并发和共享是最基本的两个特征,二者互为存在条件。没有并发和共享就谈不上虚拟和异步

并发

并发是指两个或多个事件在同一时间间隔内发生。这些事件宏观上是同时发生的,但是微观上是交替发生的。

常考易混概念:并行:指两个或多个事件在同一时刻同时发生。

操作系统的并发性是指:计算机系统中同时存在着多个运行着的程序。

一个单核处理器(CPU)同一时刻只能执行一个程序,因此操作系统会负责协调多个程序交替执行(这些程序微观上是交替执行的。但是宏观上看起来像是在同一时刻运行。)操作系统和程序并发是一起诞生的

共享

共享即资源共享,是指系统中的资源可供内存中多个并发执行的进程共同使用。

两种资源共享方式:

1.互斥共享方式(系统中的某些资源虽然可以提供给多个进程使用,但一个时间段内只允许一个进程访问该资源)

2.同时共享方式(系统中的某些资源,允许一个时间段内由多个进程同时对他们进行访问)这里的同时也分为宏观上和微观上

互斥共享方式:如qq和微信使用摄像头,同一时间只有一个可以软件可以使用。

同时共享方式:使用qq和微信同时对一个文件进行发送。宏观上看是同时读取并发送文件的,说明两个进程都在访问硬盘资源,从中读取数据。微观上看,两个进程是交替着访问硬盘的。

并发与共享的关系

如果失去并发性,则系统中只有一个程序正在运行,则共享性会失去存在的意义。

如果失去共享性,则qq和微信不能同时访问硬盘资源, 就无法实现同时发送文件,也就无法并发

虚拟

虚拟是指把一个物理上的实体变为若干个逻辑上的对应物。物理实体(前者)是实际存在的,而逻辑上对应物(后者)是用户感受到的。

虚拟技术:

1.空分复用技术(如虚拟存储器技术)

2.时分复用技术(如虚拟处理器)

异步

异步是指,在多道程序环境下,允许多个程序并发执行,但是由于资源有限,进程的执行不是一贯到底的。而是走走停停,以不可预知的速度向前推进,这就是进程的异步性。

显然,如果失去了并发性,则系统只能串行地处理各个进程,每个进程的执行会一贯到底。只有系统拥有并发性,才可能导致异步性。

操作系统的发展与分类

手工操作阶段

缺点:用户独占全机,人机速度矛盾导致资源利用率极低。

在这里插入图片描述

批处理阶段-单道批处理系统

引入脱机输入、输出技术(用磁带完成),并监督程序负责控制作业的输入和输出。

在这里插入图片描述

批处理阶段-多道批处理系统

主要优点:多道程序并发执行,共享计算机资源。资源利用率大幅提升,CPU和其他资源保持“忙碌状态”,系统的吞吐量增大。

主要缺点:用户响应时间长,没有人机交互功能(用户提交自己的作业后只能等待计算机处理完成,中间不能控制自己的作业执行)

在这里插入图片描述

为何多批道处理系统能使资源利用率大幅提升

在这里插入图片描述

分时操作系统

计算机以时间片为单位轮流为各个用户/作业服务,各个用户可以通过终端与计算机进行交互。

主要优点:用户请求可以被即时响应,解决了人机交互问题。允许多个用户同时使用一台计算机,并且用户对计算机的操作相互独立,感受不到别人的存在。

主要缺点:不能优先处理一些紧急任务,操作系统对各个用户/作业都是完全公平的,循环地为每个用户/作业服务一个时间片。不能区分任务的紧急性。

实时操作系统

主要优点:能够优先响应一些紧急任务,某些紧急任务不需要时间片排队。

在实时操作系统的控制下,计算机系统接受到外部信号后及时处理,并且要在严格的时限内处理完事件。实时操作系统的特点是及时性和可靠性。

在这里插入图片描述

其他几种操作系统

在这里插入图片描述

总结

在这里插入图片描述

操作系统的运行机制体系结构

预备知识:

什么是指令?

指令就是处理器(CPU)能识别、执行的最基本命令。比如:加法指令就是让CPU进行加法运算。

指令分为:特权指令(可能产生恶意破坏|危险:如内存清零)和非特权指令(人畜无害)

对应了两种处理器状态(用程序状态字寄存器(PSW)中的某标志位来标识当前处理器出于什么状态):

1.用户态(目态)(只可以处理非特权指令)

2.核心态(管态)(特权指令和非特权指令都可以执行)

两种程序:

1.内核程序:系统的管理者,既可以执行特权指令又可以执行非特权指令,运行在核心态

2.应用程序:为了保证系统能安全运行,普通应用程序只能执行非特权指令,运行在用户态。

操作系统中哪些功能应该由内核程序实现呢?

在这里插入图片描述

内核

内核是计算机上配置的底层软件,是操作系统最基本最核心的部分。实现操作系统内核功能的那些程序就是内核程序。

在这里插入图片描述

大内核与微内核

在这里插入图片描述

在这里插入图片描述

中断和异常

引入中断机制,实现了多道程序并发执行。

本质:发生中断意味着需要操作系统的介入,开展管理工作。

当中断发生时,CPU立即进入核心态

当中断发生后,当前运行的进程暂停运行,并由操作系统内核对中断进行处理。

对于不同的中断信号,会进行不同的操作

发生了中断就意味着需要操作系统的介入,开展管理工作。由于操作系统的管理工作(比如进程切换、分配I/O设备等)需要使用特权指令,因此CPU要从用户态转换为核心态,使操作系统获得计算机的控制权。有了中断才可以实现多道程序并发执行。

用户态切换到核心态是由中断实现的(唯一途径)

核心态到用户态的切换是通过执行一个特权指令,将程序状态字(PSW)的标志位设置为“用户态”

中断的分类

在这里插入图片描述

外中断处理过程

在这里插入图片描述

系统调用

什么是系统调用?有何作用?

操作系统作为用户和计算机硬件之间的接口,需要向上提供一些简单易用的服务,主要包括命令接口和程序接口。其中,程序接口由一组系统调用组成。

应用程序通过系统调用请求操作系统的服务。系统中的各种共享资源都由操作系统统一掌管,因此在用户程序中,凡是与资源有关的操作(如存储分配、I\\O操作、文件管理等),都必须通过系统调用的方式向操作系统提出服务请求,由操作系统代为完成。这样可以保证系统的安全性和稳定性,防止用户进行非法操作。

系统调用按功能分类

在这里插入图片描述

系统调用在核心态下完成!

系统调用和库函数的区别

在这里插入图片描述

系统调用背后的过程

传递系统调用参数–>执行陷入指令(用户态),引发一个内中断–>执行系统调用响应服务程序(核心态)–>返回用户程序

注意:陷入指令是唯一一个只能在用户态执行,而不可在核心态执行的命令

系统调用发生在用户态但是对系统调用的处理发生在核心态

进程

程序:就是一个指令序列

在这里插入图片描述

进程的定义

程序段、数据段、PCB三部分组成了进程实体(进程映像)。一般情况下,我们把进程实体就简称为进程。例如,所谓创建进程,实质上就是创建进程实体上的PCB;而撤销进程就是撤销进程实体中的PCB。

注意:PCB是进程存在的唯一标志!

引入进程实体的概念后,可把进程定义为:

进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。

注:严格来说,进程实体和进程并不一样,进程实体是静态的,进程则是动态的,不过除非题目专门考察二者的区别,否则可以认为进程实体就是进程。因此我们可以说“进程是由程序段、数据段、PCB三部分组成的。”

进程的组成

进程(进程实体)由程序段、数据段、PCB三部分组成。

在这里插入图片描述

PCB的组成

在这里插入图片描述

进程的组织

在这里插入图片描述

链接方式

在这里插入图片描述

索引方式

在这里插入图片描述

进程的特征

  1. 动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的(最基本的特性)
  2. 并发性:内存中有多个进程实体,各进程可并发执行
  3. 独立性:进程是能独立运行、独立获取资源、独立接收调度的基本单位(进程是资源分配、接受调度的基本单位)
  4. 异步性:各进程按各自独立的、不可预知的速度向前推进,操作系统要提供“进程同步机制”来解决异步问题(异步性会导致并发程序执行的不确定性)
  5. 结构性:每个进程都会配置一个PCB,结构上看,进程由程序段、数据段、PCB三部分组成

进程的状态与转换

进程的三种基本状态

在这里插入图片描述

另外两种状态

在这里插入图片描述

进程状态的转换

在这里插入图片描述

进程控制

什么是进程控制?

进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。

如何实现进程控制?

用原语实现进程控制,原语的特点是执行期间不允许中断,只能一气呵成。这种不可以被中断的操作即原子操作

原语采用了“关中断指令”和“开中断指令”实现。显然关/开中断指令的权限很大,所以是只允许在核心态下执行的特权命令。

创建原语

  • 申请空白PCB
  • 为新进程分配所需资源
  • 初始化PCB
  • 将PCB插入就绪队列

引起进程创建的事件

在这里插入图片描述

进程的终止

在这里插入图片描述

进程的阻塞和唤醒

在这里插入图片描述

进程的切换

在这里插入图片描述

进程通信

什么是进程通信?

是指进程之间的信息交换,进程是分配系统资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。

为了保证安全,一个进程不能直接访问另外一个进程的地址空间。但是进程之间的信息交换又是必须实现的,为了保证进程间的安全通信,操作系统提供了一些方法。

共享存储

在这里插入图片描述

管道通信

在这里插入图片描述

消息传递

进程间的数据交换以格式化的消息为单位,进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换。

在这里插入图片描述

线程的概念和多线程模型

什么是线程?为什么要进入线程

在这里插入图片描述

可以把线程理解为一种“轻量级的进程”,线程是一个基本的CPU执行单元,也是程序执行流的最小单位。

引入线程之后,不仅是进程之间可以并发,进程之间的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内可以并发处理各种任务。

引入线程机制后,有什么变化??

在这里插入图片描述

线程的属性

  • 线程是处理机调度的单位
  • 多CPU计算机中,各个线程可占用不同的CPU
  • 每个线程都有一个线程ID,线程控制块(TCB)
  • 线程也有就绪、阻塞、运行三种基本状态
  • 线程几乎不拥有系统资源
  • 同一进程的不同线程之间可以共享进程的资源
  • 由于共享内存地址空间,同一进程中的线程间通信甚至不需要系统干预
  • 同一进程的线程切换,不会引起进程切换
  • 不同进程的线程切换会引起进程切换
  • 切换同进程内的线程,系统开销很小
  • 切换进程系统开销很大

线程的实现方式

用户级线程(ULT)

在这里插入图片描述

内核级线程(KLT)

在这里插入图片描述

操作系统只看得见内核级线程,因此只有内核级线程才是处理机分配的单位!

多线程模型

在同时支持用户级线程和内核级线程的系统中,由几个用户级线程映射到几个内核级线程的问题引出了“多线程模型”

多对一模型:多个用户及线程映射到一个内核级线程。每个用户进程只对应一个内核级线程。

优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高。

缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可以在多核处理机上并行运行·。

在这里插入图片描述

一对一模型:一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程相同数量的内核级线程

优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上并行运行。

缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理成本高开销大。

多对多模型:在同时支持用户级线程和内核级线程的系统中,由几个用户级线程映射到几个内核级线程的问题引发了“多对多模型”

n用户级线程映射到m个内核级线程(n>m)。每个用户进程对应m个内核级线程。

处理机调度

处理机调度的概念和层次

当有一堆任务要处理,但是由于资源有限,这些事情没有办法同时处理。这就需要确定某种规则来决定处理这些任务的顺序,这就是调度研究的问题。

在多道程序程序中,进程的数量往往是多于处理机个数的,这样不可能同时并发地处理各个进程。处理机调度,就是从就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行,以实现进程的并发执行。

调度的三个层次

高级调度

由于内存空间有限,有时无法将用户提交的作业全部放入内存,因此就需要确定某种规则来决定将作业调入内存的顺序。

高级调度(作业调度)一定的原则从外存上处于后备队列的作业中挑选一个(或多个)作业,给他们分配内存等必要资源,并建立相应的进程(建立PCB) ,以使它(们)获得竞争处理机的权利。

高级调度是辅存(外存)与内存之间的调度。每个作业只调入一次,调出一次。作业调入时会建立相应的PCB,作业调出时才撤销PCB。高级调度主要是指调入的问题,因为只有调入的时机需要操作系统来确定,但调出的时机必然是作业运行结束才调出。

中级调度

引入了虚拟存储技术之后,可将暂时不能运行的进程调至外存等待。等它重新具备了运行条件且内存又稍有空闲时,再重新调入内存。这么做的目的是为了提高内存利用率系统吞吐量

暂时调到外存等待的进程状态为挂起状态。值得注意的是,PCB并不会一起调到外存, 而是会常驻内存。PCB中会记录进程数据在外存中的存放位置,进程状态等信息,操作系统通过内存中的PCB来保持对各个进程的监控、管理。被挂起的进程PCB会被放到的挂起队列中。

中级调度(内存调度),就是要决定将哪个处于挂起状态的进程重新调入内存。

一个进程可能会被多次调出、调入内存,因此中级调度发生的频率要比高级调度更高

扩展:进程的挂起状态和七状态模型

在这里插入图片描述

低级调度

低级调度(进程调度),其主要任务是按照某种方法和策略从就绪队列中选取一个进程,将处理机分配给它。
进程调度是操作系统中最基本的一种调度,在一般的操作系统中都必须配置进程调度。进程调度的频率很高,一般几十毫秒一次。

总结

在这里插入图片描述

进程调度的时机

在这里插入图片描述

进程调度的方式

在这里插入图片描述

进程的切换与过程

在这里插入图片描述

调度算法的评价指标

CPU利用率:忙碌时间/总时间

系统吞吐量:单位时间内完成作业的数量

周转时间(个人更在乎):作业被提交给系统开始,到作业完成为止的这段时间间隔

它包括四个部分:作业在外存后备队列.上等待作业调度( 高级调度)的时间、进程在就绪队列上等待进程调度(低级调度)的时间、进程在CPU上执行的时间、进程等待I/O操作完成的时间。后三项在一个作业的整个处理过程中,可能发生多次。

平均周转时间(操作系统更在乎):各作业周转时间/作业数量

带权周转时间:(作业完成时间-作业提交时间)/作业实际运行的时间

平均带权周转时间:各作业带权周转时间之和/作业量

等待时间:指进程/作业出于等待处理机状态时间之和,等待时间越长用户满意度越低。

一个作业总共需要被CPU服务多久,被I/O设备服务多久一般是确定不变的,因此调度算法其实只会影响作业/进程的等待时间。

响应时间:从用户提交请求到首次产生响应所用的时间

在这里插入图片描述

调度算法

先来先服务(FCFS)

在这里插入图片描述

在这里插入图片描述

最短作业优先(SJF)

在这里插入图片描述

最高响应比优先(HRRN)

在这里插入图片描述

在这里插入图片描述

批处理系统处理调度算法

在这里插入图片描述

调度算法

时间片轮转(RR)

如果时间片太大,使得每个进程都可以在一个时间片内就完成,则时间片轮转调度算法退化为先来先服务调度算法,并且会增大进程响应时间,因此时间片不能太大

另一方面,进程调度、切换是有时间代价的(保存、恢复运行环境),因此如果时间片太小,会导致进程切换过于频繁,系统会花大量的时间来处理进程切换,从而导致实际用于进程执行的时间比例减少。可见时间片也不能太小

一般来说,设计时间片时让切换进程的开销占比不超过1%

在这里插入图片描述

优先级调度

在这里插入图片描述

多级反馈队列

在这里插入图片描述

总结

在这里插入图片描述

进程同步和进程互斥

进程同步

同步亦称直接制约关系,它是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而产生的制约关系。进程间的直接制约关系就是源于它们之间的相互合作。

进程互斥

我们把一个时间段内只允许一个进程使用的资源称为临界资源。许多物理设备(比如摄像头、打印机)都属于临界资源。此外还有许多变量、数据、内存缓冲区等都属于临界资源。

对临界资源的访问,必须互斥地进行。互斥,亦称间接制约关系。进程互斥指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待。当前访问临界资源的进程访问结束,释放该资源之后,另一个进程才能去访问临界资源。

对临界资源的互斥访问可以在逻辑上分为以下四个部分:

在这里插入图片描述

为了实现对临界资源的互斥访问,同时保证系统整体性能,需要遵循以下原则

在这里插入图片描述

进程互斥的软件实现方法

单标志法

算法思想:两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进程赋予。

在这里插入图片描述

双标志先检查法

在这里插入图片描述

双标志后检查法

在这里插入图片描述

Peterson算法


在这里插入图片描述

进程互斥的硬件实现方法

中断屏蔽方法

在这里插入图片描述

TestAndSet(TS指令/TSL指令)

在这里插入图片描述

Swap指令(XCHG指令)

在这里插入图片描述

信号量机制

信号量其实就是一个变量(可以是一个整数,也可以是更复杂的记录型变量),可以用一个信号量来表示系统中某种资源的数量,比如:系统中只有一台打印机,就可以设置一个初值为1的信号量。

原语是一种特殊的程序段,其执行只能一气呵成,不可被中断。原语是由关中断/开中断指令实现的。软件解决方案的主要问题是由“进入区的各种操作无法一气呵成”,因此如果能把进入区、退,出区的操作都用“原语”实现,使这些操作能“一气呵成”就能避免问题。

一对原语:wait(S)原语和signal(S)原语,可以把原语理解为我们自己写的函数,函数名分别为wait和signal,括号里的信号量S其实就是函数调用时传入的一个参数。wait、signal原语常简称为P、V操作(来自荷兰语proberen和verhogen)。因此,做题的时候常把wait(S)、signal(S) 两个操作分别写为P(S)、V(S)。

整型信号量

用一个整数型的变量作为信号量,用来表示系统中某种资源的数量。(与普通整数变量的区别,对信号量的操作只有三种,即初始化,P操作,V操作)

在这里插入图片描述

记录型信号量

整型信号量的缺陷是存在忙等问题,因此人们又提出了“记录型信号量”,即用记录型数据结构表示的信号量。

在这里插入图片描述

在这里插入图片描述

用信号量机制实现进程互斥、同步、前驱关系

用信号量机制实现进程互斥

1.分析并发进程的关键活动,划分临界区(如:对临界资源打印机的访问就应该放在临界区)

2.设置互斥信号量mutex,初值为1

在这里插入图片描述

用信号量机制实现进程同步

进程同步:要让各并发进程按要求有序地推进。

用信号量机制实现进程同步:

1.分析什么地方需要实现“同步关系”,即必须保证“一前一后“执行的两个操作(或两句代码)

2.设置同步信号量S,初始为0。

3.在”前操作“之后执行一个V(S)

4.在”后操作“之前执行一个P(S)

在这里插入图片描述

信号量机制实现前驱关系

在这里插入图片描述

生产者消费者问题

系统中有一组生产者和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用(这里的产品可以理解为某种数据)

在这里插入图片描述

实现互斥的P操作一定要在实现同步的P操作之后

V操作不会导致进程阻塞,因此v操作顺序可以交换

生产者消费者问题就是一个进程互斥和进程同步的综合问题

在这里插入图片描述

多生产者多消费者问题

在这里插入图片描述

在这里插入图片描述

总结:在生产者-消费者问题中,如果缓冲区大小为1,那么有可能不需要设置互斥信号量就可以实现,互斥访问缓冲区的功能。当然,这不是绝对的,要具体问题具体分析。

建议:在考试中如果来不及仔细分析,可以加上互斥信号量,保证各进程一定会互斥地访问缓冲区。但需要注意的是,实现互斥的P操作一定要在实现同步的P操作之后,否则可能引起“死锁”。

PV操作题目的解题思路:
1.关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。
2.整理思路。根据各进程的操作流程确定P、V操作的大致顺序。
3.设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。( 互斥信号量初值一般为1,同步信号量的初始值要看对应资源的初始值是多少)

在这里插入图片描述

吸烟者问题

在这里插入图片描述

在这里插入图片描述

读者-写者问题

问题描述

在这里插入图片描述

问题分析

在这里插入图片描述

解决方法

在这里插入图片描述

读者-写者问题为我们解决复杂的互斥问题提供了一个参考思路。其核心思想在于设置了一个计数器count用来记录当前正在访问共享文件的读进程数。我们可以用count的值来判断当前进入的进程是否是第一个/最后一个读进程,从而做出不同的处理。

另外,对count变量的检查和赋值不能一气呵成导致了一些错误,如果需要实现“一气呵成”,自然应该想到用互斥信号量
最后,还要认真体会我们是如何解决“写进程饥饿”问题的。

绝大多数的考研PV操作大题都可以用之前介绍的几种生产者-消费者问题的思想来解决,如果遇到更复杂的问题,可以想想能否用读者写者问题的这几个思想来解决。

哲学家进餐问题

问题描述

一张圆桌上坐着5名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。

在这里插入图片描述

哲学家进餐问题的关键在于解决进程死锁。

这些进程之间只存在互斥关系,但是与之前接触到的互斥关系不同的是,每个进程都需要同时持有两个临界资源,因此就有“死锁”问题的隐患。如果在考试中遇到了一个进程需要同时持有多个临界资源的情况,应该参考哲学家问题的思想,分析题中给出的进程之间是否会发生循环等待,是否会发生死锁。

管程

为什么要引入管程

信号量机制存在的问题:编写程序困难,易出错

能不能设计一种机制,让程序员写代码的时候不在关注复杂的pv操作,让写代码更加轻松呢?

管程的定义和基本特征

管程是一种特殊的软件模块,有这些部分组成:
1.局部于管程的共享数据结构说明;
2.对该数据结构进行操作的一组过程;
3.对局部于管程的共享数据设置初始值的语句;
4.管程有一个名字。

管程的基本特征:
1.局部于管程的数据只能被局部于管程的过程所访问;
2.一个进程只有通过调用管程内的过程才能进入管程访问共享数据;
3.每次仅允许一个进程在管程内执行某个内部过程。

用管程解决生产者消费者问题

在这里插入图片描述

引入管程的目的无非就是要更方便地实现进程互斥和同步。(封装思想)
1.需要在管程中定义共享数据(如生产者消费者问题的缓冲区)

2.需要在管程中定义用于访问这些共享数据的“入口”——其实就是一些函数(如生产者消费者问题中,可以定义一一个函数用于将产品放入缓冲区,再定义一个函数用于从缓冲区取出产品)。

3.只有通过这些特定的“入口”才能访问共享数据

4.管程中有很多“入口”,但是每次只能开放其中一个“入口”,并且只能让一个进程或线程进入(如生产者消费者问题中,各进程需要互斥地访问共享缓冲区。管程的这种特性即可保证一个时间段内最多只会有一个进程在访问缓冲区。注意:这种,互斥特性是由编译器负责实现的,程序员不用关心)。

5.可在管程中设置条件变量及等待/唤醒操作以解决同步问题。可以让一个进程或线程在条件变量上等待(此时,该进程应先释放管程的使用权,也就是让出“入口”) ;可以通过唤醒操作将等待在条件变量上的进程或线程唤醒。

Java中类似于管程的机制

在这里插入图片描述

死锁

死锁的概念

什么是死锁?

每个人都占有一个资源,同时又在等待另一个人手里的资源,发生死锁

在并发环境下,各进程因竞争资源而造成的一种互相等待对方手里的资源,导致各进程都阻塞,都无法向前推进的现象,就是“死锁”,发生死锁后若无外力干涉,这些进程都将无法向前推进。

进程死锁、饥饿、死循环的区别

饥饿: 由于长期得不到想要的资源,某进程无法向前推进的现象。比如:在短进程优先(SPF) 算法中,若有源源不断的短进程到来,则长进程将一直得不到处理机,从而发生长进程“饥饿”。

死循环:某进程执行过程中-直跳不出某个循环的现象。有时是因为程序逻辑bug导致的,有时是程序员故意设计的。

在这里插入图片描述

死锁产生的必要条件

在这里插入图片描述

什么时候会发生死锁?

1.对系统资源的竞争。各进程对不可剥夺的资源( 如打印机)的竞争可能引起死锁,对可剥夺的资源(CPU)的竞争是不会引起死锁的。

2.进程推进顺序非法。请求和释放资源的顺序不当,也同样会导致死锁。例如,并发执行的进程P1、P2分别申请并占有了资源R1、R2,之后进程P1又紧接着申请资源R2,而进程P2又申请资源R1,两者会因为申请的资源被对方占有而阻塞,从而发生死锁。

3.信号量的使用不当也会造成死锁。如生产者-消费者问题中,如果实现互斥的P操作在实现同步的P操作之前,就有可能导致死锁。(可以把互斥信号量、同步信号量也看做是-种抽象的系统资源)

总之,对不可剥夺资源的不合理分配可能导致死锁

死锁的处理策略

1.预防死锁。破坏死锁产生的四个必要条件中的一个或几个。
2.避免死锁。用某种方法防止系统进入不安全状态,从而避免死锁(银行家算法)
3.死锁的检测和解除。允许死锁的发生,不过操作系统会负责检测出死锁的发生,然后采取某种措施解除死锁A。

死锁的处理策略——预防死锁

破坏互斥条件

互斥条件:只有对必须互斥使用的资源的争抢才会导致死锁。

在这里插入图片描述

破坏不剥夺条件

不剥夺条件:进程所获得的资源在未使用完之前,不能由其他进程强行夺走,只能主动释放。

方案一:当某个进程请求新的资源得不到满足时,它必须立即释放保持的所有资源,待以后需要时再重新申请。也就是说,即使某些资源尚未使用完,也需要主动释放,从而破坏了不可剥夺条件。

方案二:当某个进程需要的资源被其他进程所占有的时候,可以由操作系统协助,将想要的资源强行剥夺。这种方式一-般需要考虑各进程的优先级(比如:剥夺调度方式,就是将处理机资源强行剥夺给优先级更高的进程使用)

该策略的缺点:

1.实现起来比较复杂。

2.释放已获得的资源可能造成前一阶段工作的失效。因此这种方法一般只适用于易保存和恢复状态的资源,如CPU。

3.反复地申请和释放资源会增加系统开销,降低系统吞吐量。

4.若采用方案一,意味着只要暂时得不到某个资源,之前获得的那些资源就都需要放弃,以后再重新申请。如果一直发生这样的情况,就会导致进程饥饿。

破坏请求和保持条件

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

可以采用静态分配方法,即进程在运行前一次申请完它所需要的全部资源,在它的资源未满足前,不让它投入运行。一旦投入运行后,这些资源就一直归它所有,该进程就不会再请求别的任何资源了。

该策略实现起来简单,但也有明显的缺点:
有些资源可能只需要用很短的时间,因此如果进程的整个运行期间都一直保持着所有资源,就会造成严重的资源浪费,资源利用率极低。另外,该策略也有可能导致某些进程饥饿

破坏循环等待条件

循环等待条件:存在一种进程资源的循环等待链,链中的每一个进程已获得的资源同时被下一个进程所请求。

在这里插入图片描述

死锁的处理策略——避免死锁

什么是安全序列

所谓的安全序列就是如果系统按照这种序列分配资源,则每个进程都能够顺利完成。只要你能找出一个安全序列,系统就是安全状态,当然,安全序列可能有多个。

什么是系统的不安全状态,与死锁有何联系

如果分配了资源之后,系统中找不出任何一个安全序列,系统就进入了不安全状态。这就意味着之后可能所有进程都无法顺利的执行下去。当然,如果有进程提前归还了一些资源,那系统也有可能重新回到安全状态,不过我们在分配资源之前总是要考虑到最坏的情况。

如果系统处于安全状态,就一定不会发生死锁。如果系统进入不安全状态,就可能发生死锁(处于不安全状态未必就是发生了死锁,但发生死锁时一定是在不安全状态)。

因此可以在资源分配之前预先判断这次分配是否会导致系统进入不安全的状态,以此决定是否答应资源分配请求,这也是银行家算法的核心思想。

如何避免系统进入不安全状态——银行家算法

在这里插入图片描述

死锁的处理策略——检测和解除

死锁的检测

为了能对系统是否已发生了死锁进行检测,必须:
①用某种数据结构来保存资源的请求和分配信息;
②提供一种算法,利用上述信息来检测系统是否已进入死锁状态。

检测死锁的算法:
1)在资源分配图中,找出既不阻塞又不是孤点的进程Pi(即找出一条有向边与它相连,且该有向边对应资源的申请数量小于等于系统中已有空闲资源数量。如下图中,R1没有空闲资源,R2有一个空闲资源。若所有的连接该进程的边均满足上述条件,则这个进程能继续运行直至完成,然后释放它所占有的所有资源)。消去它所有的请求边和分配变,使之称为孤立的结点。

2)进程Pi所释放的资源,可以唤醒某些因等待这些资源而阻塞的进程,原来的阻塞进程可能变为非阻塞进程。根据1)中的方法进行一系列简化后,若能消去途中所有的边,则称该图是可完全简化的。

死锁定理
如果某时刻系统的资源分配图是不可完全简化的,那么此时系统死锁。

死锁的解除

一旦检测出死锁的发生,就应该立即解除死锁。

补充:并不是系统中所有的进程都是死锁状态,用死锁检测算法简化资源分配图后,还连着边的那些进程是死锁进程。

解除死锁的主要方法

1.资源剥夺法。挂起(暂时放到外存上)某些死锁进程,并抢占它的资源,将这些资源分配给其他的死锁进程。但是应防止被挂起的进程长时间得不到资源而饥饿。

2.撤销进程法(或称终止进程法)。强制撤销部分、甚至全部死锁进程,并剥夺这些进程的资源。这种方式的优点是实现简单,但所付出的代价可能会很大。因为有些进程可能已经运行了很长时间,已经接近结束了,一旦被终止可谓功亏一篑,以后还得从头再来。

3.进程回退法。让一个或多个死锁进程回退到足以避免死锁的地步。这就要求系统要记录进程的历史信息,设置还原点。

如何决定对谁“动手”

1.进程优先级
2.已执行多长时间
3.还要多久能完成
4.进程已经使用了多少资源
5.进程是交互式的还是批处理式的

内存

内存的基础知识

什么是内存?,有何作用

内存是用于存放数据的硬件,程序执行前需要先放到内存中才能被CPU处理。

在这里插入图片描述

补充知识:

几个常用的数量单位

一台电脑有4G内存是什么意思?

是指该内存中可以存放4*2的30次方个字节,如果是按字节编址的计算机,也就是2的32次方个小房子。这么多小房间,需要2的32次方个地址才能一一标识,所以地址需要用32个二进制来表示(0-2的32次方-1)

2的10次方=1K、2的20次方=1M、2的30次方=1G

进程运行的基本原理

在这里插入图片描述

从写程序到程序运行

编译:由编译程序将用户源代码编译成若干个目标模块(编译就是把高级语言翻译为机器语言)

链接:由链接程序将编译后形成的一组目标模块,以及所需要的库函数链接在一起,形成一个完整的装入模块

装入(装载):由装入程序将装入模块装入内存运行。

在这里插入图片描述

装入模块装入内存

装入的三种方式(用三种不同的方式完成逻辑地址到物理地址的转换)

1.绝对装入方式

绝对装入:在编译时,如果知道程序将放到内存中的哪个位置,编译程序将产生绝对地址的目标代码。装入程序按照装入模块中的地址,将程序和数据装入内存。

绝对装入只适用于单道程序环境

程序中使用的绝对地址,可在编译或汇编时给出,也可由程序员直接赋予。通常情况下都是编译或汇编时再转换为绝对地址。

2.静态重定位

静态重定位:又称**可重定位装入。**编译、链接后的装入模块的地址都是从0开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址。可根据内存的当前情况,将装入模块装入到内存的适当位置。装入时对地址进行“重定位”,将逻辑地址变换为物理地址( 地址变换是在装入时一次完成的)。

静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业。作业一旦进入内存后,在运行期间就不能再移动也不能再申请内存空间

3.动态重定位

动态重定位:又称动态运行时装入。编译、链接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序真正要执行时才进行。因此装入内存后所有的地址依然是逻辑地址。这种方式需要-一个重定位寄存器的支持。

采用动态重定位时允许程序在内存中发生移动。

链接的三种方式
1.静态链接:在程序运行之前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(装入模块),之后不再拆开。

2.装入时动态链接: 将各目标模块装入内存时,边装入边链接的链接方式。

3.运行时动态链接:在程序执行中需要该目标模块时,才对它进行链接。其优点是便于修改和更新,便于实现对目标模块的共享。

内存管理的概念

内存空间的分配和回收

操作系统负责内存空间分配与回收

内存空间的扩充

操作系统需要提供某种技术从逻辑上对内存空间进行扩充(操作系统的虚拟性)

地址转换

为了使编程更方便,程序员写程序时应该只需要关注指令、数据的逻辑地址。而逻辑地址到物理地址的转换(这个过程称为地址重定位)应该由操作系统负责,这样就保证了程序员写程序时不需要关注物理内存的实际情况。

存储保护

操作系统需要提供内存保护功能,保证各进程在各自存储空间内运行,互不干扰。

在这里插入图片描述

在这里插入图片描述

覆盖与交换

覆盖技术

解决“程序大小超过物理内存总和”的问题

覆盖技术的思想核心:将程序分为多个段(多个模块)常用的段(模块)常驻内存,不常用的段在需要的时候调入内存。

内存中分为一个“固定区”和若干个“覆盖区”。需要常驻内存的段放入在“固定区”,调入后就不再调出(除非运行结束)

不常用的段存放在“覆盖区”,需要的时候调入内存,不需要的时候调出内存。

例子:

在这里插入图片描述

交换技术

交换(对换)技术的设计思想:内存空间紧张时,系统将内存中某些进程暂时换出外存,把外存中某些己具备运行条件的进程换入内存(进程在内存与磁盘间动态调度)

暂时换出外存等待的进程状态成为挂起状态(挂起态,suspend)

挂起态又可以进一步分为就绪挂起和阻塞挂起两种状态

PCB会常驻内存,不会被换出外存

1.应该在外存(磁盘)的什么位置保存被换出的进程呢?

具有对换功能的操作系统中,通常把磁盘空间分为文件区和对换区两部分。文件区主要用于存放文件,主要追求存储空间的利用率,因此对文件区空间的管理采用离散分配方式;对换区空间只占磁盘空间的小部分,被换出的进程数据就存放在对换区

以上是关于操作系统——呕心沥血长篇总结(王道考研)的主要内容,如果未能解决你的问题,请参考以下文章

操作系统——呕心沥血长篇总结(王道考研)

操作系统王道考研 笔记总结(持续更新)

专栏必读王道考研408操作系统+Linux系统编程万字笔记题目题型总结注意事项目录导航和思维导图

操作系统王道考研 p27 管程

操作系统学习笔记 第一章:操作系统概述(王道考研)

操作系统学习笔记 第一章:操作系统概述(王道考研)