欢迎光临散文网 会员登陆 & 注册

操作系统(三)——进程管理(上)

2023-03-07 20:30 作者:UCLmsc  | 我要投稿

一、进程与线程

1. 进程的概念、组成、特征

在多道程序环境下,允许多个程序并发执行,此时他们将失去封闭性,并具有间断性和不可再现性的特征。为此引入了进程的概念,以便更好地描述和控制程序的并发执行,实现操作系统的并发行和共享性。为此引入了进程的概念,以便更好地描述和控制程序的并发执行,实现操作系统的并发性和共享性。

为了是参与并发执行的程序能独立的运行,必须为之配置一个专门的数据结构,称之为进程控制块(process control block),系统利用PCB来描述进程的基本情况和运行状态,进而控制和管理进程。

相应的,有程序段、相关数据段和PCB三部分构成了进程映像(进程实体)。所谓创建进程,实质上是创建进程映像中的PCB;而撤销进程,实质上是撤销进程的PCB。指的注意的是,进程影响是静态的,进程是动态的。

从不同的角度,进程可以有不同的定义,比较经典的定义有:

1) 进程是程序的一次执行过程

2) 进程是一个程序及其数据在处理器上顺序执行时所发生的活动。

3) 进程是具有独立功能的程序在一个数据集合上运行的过程,他是系统进行资源分配和调度的一个独立单位。

在引入了进程实体的概念后,我们可以吧传统的操作系统中的进程定义为:“进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位”。


进程的概念主要有两点:第一,进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(text region)、数据区域(data region)和堆栈(stack region)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。第二,进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时(操作系统执行之),它才能成为一个活动的实体,我们称其为进程。

描述进程—–PCB

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。

课本上称之为PCB(process control block),Linux操作系统下的PCB是: task_struct 。

在Linux中描述进程的结构体叫做task_struct。

task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)⾥里并且包含着进程的信息。

task_ struct内容分类

进程的特征:

进程是由多程序的并发执行而引出的,他和程序是两个截然不同的概念。进程的基本特征是对比单个程序的顺序执行提出的,也是对进程管理提出的基本要求。

1) 动态性:进程是程序的一次执行,他有着创建、活动、暂停、终止等过程,具有一定的生命周期,是动态的产生、变化和消亡的。动态性是进程最基本的特征。

2) 并发性:至多个进程实体,同存于内存中,能在一段时间内同时运行,并发性是进程的重要特征,同时也是操作系统的重要特征,引入进程的目的就是为了是程序能与去其他进程的程序并发执行,以提高资源利用率。

3) 独立性:指进程实体是一个能独立运行、独立获得资源和独立接收调度的基本单位。范围建立PCB的程序都不能作为一个独立的单位参与运行。

4) 异步性:由于进程的相互制约,是进程具有执行的间断性。也即进程按各自独立的、不可预知的速度向前推进。异步性会导致执行结果不可再现性,为此,在操作系统中必须配置相应的进程同步机制。

5) 结构性:每个进程都配置一个PCB对其进行描述。从结构上来看,进程实体是由程序段、数据段和进程控制端三部分组成的。

PCB

上下文”在计算机领域指的是程序执行时的环境和条件,包括程序当前的状态、变量的值、执行的代码位置、程序的输入和输出等。在编程中,上下文通常被用来描述程序的执行环境,以便正确地理解和处理程序的行为。上下文还可以用于调试、优化和测试程序,以确保程序在不同的上下文中都能正确地运行。上下文切换是指操作系统在进行多任务处理时,由于需要切换当前任务的上下文(包括寄存器、内存空间、堆栈等),而进行的一种操作。在一个时间片内,操作系统会按照一定的时间分配策略,将 CPU 的控制权交给不同的任务,这就需要进行上下文切换。上下文切换是操作系统中非常重要的一项技术,它能够保证多个任务在同一时间内得到有效的执行,从而提高了计算机的效率。

PCB的组织

PCB表的组织方式主要有:线性方式、链接方式和索引方式。

· 线性方式是把所有进程的PCB都放在一个表中。

· 链接方式按照进程的不同状态把它们分别放在不同的队列中。

· 索引方式是利用索引表记载相应状态进程的PCB地址。

2. 进程的状态与转换

进程在其生命周期内,由于系统中个进程之间的相互制约关系以及系统的运行环境的变化,使的进程的状态也在不断地发生着变化。通常进程有以下五种状态。前三种是进程的基本状态。

1) 运行状态:进程正在处理器上运行。在单处理器的环境下,每一时刻最多只有一个进程处于运行状态。

2) 就绪状态:进程已处于准备运行的状态,即进程获得了除CPU之外的一切所需资源,一旦得到处理器即可运行。

3) 阻塞状态:又称为等待状态:进程正在等待某一事件而暂停运行,如等待某资源为可用(不包括处理器),或等待输入输出的完成。即使处理器空闲,该进程也不能运行。

4) 创建状态:进程正在被创建,尚未转到就绪状态。创建进程通常需要多个步骤:首先申请一个空白的PCB,并向PCB中填写一些控制和管理进程的信息;然后由系统为该进程分配运行时所必须的资源;最后把该进程转入到就绪状态。

5) 结束状态:进程正在从系统中消失,这可能是进程正常结束或其他原因中断退出运行。当进程需要结束运行时,系统首先必须置该进程为结束状态,然后再进一步处理资源释放和回收工作。

注意区别就绪状态和等待状态:就绪状态是指进程仅缺少处理器,只要活得处理器资源就立即执行;而等待状态是指进程需要其他资源或等待某一事件,及时处理器空闲也不能运行。

处理机包括中央处理器,主存储器,输入-输出接口,加接外围设备就构成完整的计算机系统。处理机是处理计算机系统中存储程序和数据,并按照程序规定的步骤执行指令的部件。程序是描述处理机完成某项任务的指令序列。指令则是处理机能直接解释、执行的信息单位。

3. 进程控制

进程的创建和终止

进程控制的主要功能是对系统中所有进程实施有效地管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。在操作系统中,一般把进程控制用的程序段称为原语,原语的特点是执行期间不允许中断,它是一个不可分割的基本单位。

允许一个进程创建另一个进程。

操作系统创建一个新进程的过程如下(创建原语):

1) 为新进程分配一个唯一进程标示号,并申请一个空白的PCB。

2) 为进程分配资源,为新进程的程序和数据,以及用户占分配必要的空间。

3) 初始化PCB,主要包括初始化标识信息、初始化处理器状态信息和初始化处理器控制信息,以及设置进程的优先级。

4) 如果进程就绪队列能够接纳新进程,就将新进程插入到就绪队列,等待被调度运行。

引起进程终止的时间主要有:正常结束、表示进程的任务已经完成和准备退出运行。异常结束是指进程在运行时,发生了某种异常事件,是程序无法继续运行,如:存储区越界、保护错误、非法指令、特权指令错误、IO故障等。外界干预是指进程外界的请求而终止,如操作员或操作系统干预、父进程请求和父进程终止。

操作系统终止进程的过程如下:(撤消原语)

1) 根据被终止进程的标示符,检索PCB,从中读出该进程的状态。

2) 若被终止进程处于执行状态,立即终止该进程的执行,将处理器资源分配给其他进程。

3) 若该进程还有子进程,则应将其所有子进程终止。

4) 将该进程所拥有的资源、或归还给父进程或归还给操作系统。

5) 将该PCB从所在队列(链表)中删除。

计算机进程的控制通常由原语完成。所谓原语,一般是指由若干条指令组成的程序段,用来实现某个特定功能,在执行过程中不可被中断。

进程的阻塞和唤醒:

正在执行的进程,犹豫期待的某些时间为发生,如请求系统资源失败、等待某种操作的完成、新数据尚未到达或无新工作可做等,则由系统自动执行阻塞原语,使自己由运行状态变为阻塞状态。可见,进程的阻塞是进程自身的一种主动行为。

阻塞原语的执行过程为:找到将要被阻塞进程的标识号对应的PCB,如果该进程为运行状态,则保护其现场,将其状态改为阻塞状态,停止运行,并把该PCB插入响应时间的等待队列中去;若为就绪状态,则将其状态改为阻塞状态,把它溢出就绪队列,插入到等待队列中去。

当阻塞进程所期待的时间出现时,如它所启动的IO操作已完成或其所期待的数据已到达,则有关进程(比如,提供数据的进程),调用唤醒原语,将等待该事件的进程唤醒,唤醒原语的执行过程是:在该事件的等待队列中找到相应进程的PCB,然后把该PCB插入到就绪队列中,等待调度程序调度。

需要注意的是,Block原语和Wakeup原语是一对作用刚好相反的原语,必须成对使用。Block原语是由被阻塞进程自我调用实现的,而Wakeup原语则是由一个与被唤醒进程相合作或被其他相关进程调用实现的。

无论什么样的进程操作,都是在内核执行的。

进程的切换

进程切换是指当前正在运行的进程被转换到其他状态后,再回到运行继续执行的过程,这个过程中,进程的运行环境产生了实质性的变化。进程切换的过程如下:

1) 保存处理器上下文,包括程序计数器和其他寄存器。

2) 更新PCB信息。

3) 把进程的PCB移入相应的队列,如就绪、在某时间阻塞等队列。

4) 选择另一个进程执行,并更新其PCB。更新内存管理的数据结构。

5) 恢复处理器的上下文。

4. 线程

引入进程的目的,是为了是多道程序能并发执行,以提高资源利用率和系统吞吐量;而引入线程,则是为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。

线程最直接的理解就是“轻量级进程”,它是一个基本的CPU执行单元,也是程序执行流的最小单元,由线程ID、程序计数器、寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位。进程只作为除CPU以外的系统资源的分配单元,线程则作为处理器的分配单元。线程也有就绪、阻塞和运行三种基本状态。

程序执行的最小单元,是由寄存器集合和堆栈组成,线程是进程中的一个实体,可共享同一进程中所拥有的全部资源。线程,有时被称为轻量级进程(Lightweight Process,LWP),是操作系统调度(CPU调度)执行的最小单位。协程(coroutine)是一种程序组件,是一种比线程更加轻量级的存在。正如一个进程可以有多个线程,一个线程可以有多个协程。程序可以控制协程的暂停,如Python关键字yield,Go关键字go,都可实现协程暂停,而线程的阻塞是有操作系统控制。在任务调度上,协程是弱于线程的。但是在资源消耗上,协程则是极低的。一个线程的内存在 MB 级别,而协程只需要 KB 级别。而且线程的调度需要内核态与用户的频繁切入切出,资源消耗也不小。

线程的特点


线程和进程的比较

1) 调度:在引入线程的操作系统中,线程是独立调度的基本单位,进程是资源拥有的基本单位。

2) 拥有资源:进程是拥有资源的基本单位,而线程不拥有系统资源,单线程可以访问其隶属进程的系统资源。

3) 并发性:在引入线程的操作系统中,不仅进程之间可以并发执行,线程之间也可以并发执行,从而是操作系统具有更好的并发性,大大提高了系统的吞吐量。

4) 系统开销:线程开销极小。

5) 地址空间和其他资源:进程的地址空间之间相互独立,同一进程的各线程间共享进程的资源,进程内的线程对进程外的其他进程不可见。

6) 通信方面:进程间通信需要进程同步和互斥手段的辅助,以保证数据的一致性,而线程间可以直接读写进程数据段来进行通信。

线程的属性


线程的主要属性如下:

1) 线程是一个轻型实体,它不拥有系统资源,但每个线程都应有一个唯一的标识符和一个线程控制块,线程控制块记录了线程执行的寄存器和栈等现场情况。

2) 不同的线程可以执行相同的程序,即同一个服务程序被不同的用户调用时,操作系统为他们创建不同的线程。

3) 统一进程中的各个线程共享该进程所拥有的系统资源。

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

5) 一个线程被创建后便开始了它的生命周期,直至终止,线程在生命周期内会经历等待态、就绪态和运行态等各种状态变化。

线程的实现可以分为两类:用户级线程和内核级线程。

(操作系统对)线程的实现

轻权是指一种允许进程在系统中的不同级别上并行执行的机制。轻权进程是一种特殊的进程,它不会被优先执行,而是在其他级别上执行。
轻权进程在执行过程中,需要 CPU、内存等资源。因此,它们往往比优先级更高的进程更为繁忙。但是,由于它们可以并行执行,所以在某些情况下,系统会需要更多的资源来处理轻权进程。
轻权进程在网络系统中很常见,因为它们通常需要处理大量的数据包处理请求。此外,轻权进程也可以用于在多个用户程序之间进行通信。
总结一下,轻权进程是一种允许多个用户程序并行执行的机制,但是它们需要 CPU、内存等资源来保证它们能够执行。

多线程模型

有些系统同时支持用户线程和内核线程,由此产生了不同的多线程模型,即实现用户级线程和内核级线程的连接方式。

1) 多对一模型。多对一模型将多个用户级线程映射到一个内核级线程。线程管理在用户空间完成。

2) 一对一模型。

3) 多对多模型。

特点:克服了多对一模型的并发度不高的缺点,又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。

线程的状态与转换


二、进程调度和线程调度

1.调度的概念、层次

调度的概念

在多道程序系统中,进程的数量往往多于处理器的个数,进程争用处理器的情况在所难免。处理器调度是对处理器进行分配,就是从就绪队列中,按照一定的算法,选择一个进程并将处理器分配给他运行,以实现进程的并发执行。

处理器调度是多道程序操作系统的基础,它是操作系统设计的核心问题。

一个作业从提交开始直到完成,往往要经历以下三级调度:

1)作业调度。作业调度又称高级调度:其主要任务是按一定的原则从外存上处于后备状态的作业中挑选一个或多个作业,给他们分配内存、输入输出设备等必要的资源。并建立相应的进程,以使他们获得竞争处理器的权利。

多道批处理系统中大多配有作业调度,而其它系统中通常不需要配置作业调度。作业调度的执行频率较低,通常为几分钟一次。

2)中级调度。中级调度又称内存调度。引入中级调度视为了提高内存利用率和系统吞吐率,为此,应使那些暂时不能运行的进程调至外存等待,把此时的进程状态称为挂起状态。当他们已具备运行条件且内存有稍有空闲时,由中级调度来决定,吧外存上那些已具备运行条件的就绪进程,在重新调入内存,并修改其状态为就绪状态,挂在就绪队列上等待。

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

作业调度从外存的后备队列中选择一批作业进入内存,为他们建立进程。这些进程被送入就绪队列。进程调度从就绪队列中选出一个进程,并把其状态改为运行状态,把CPU分配给它。中级调度是位于高级调度和低级调度之间的一种调度。为了提高内存的利用率,系统将那些暂时不能运行的进程挂起来。当内存空间宽松时,通过中级调度选择具备运行条件的进程,将其唤醒。

调度的层次

处理机调度是指在多个用户程序同时运行时,对每一个用户程序进行优先级排序,并分配适当的处理机资源给用户程序。
进程调度是指在一个进程运行时,对该进程进行优先级排序,并为其分配适当的 CPU和内存资源。这通常是一个单独的过程,并不涉及处理机调度。
两者最大的区别在于,处理机调度是针对单个处理机进行的调度,而进程调度则是对多个进程同时进行的调度。

作业调度

进程调度


实时调度

多处理机调度

2.调度的时机、切换与过程、 方式

调度的时机、切换与过程

进程调度和切换程序是操作系统内核程序。当请求调度的事件发生后,才可能会运行进程调度程序,当调度了新的就绪进程后,才会去进行进程间的切换。

现在操作系统中,不能进行进程的调度与切换的情况有以下几种:

1) 在处理中断的过程中:中断处理过程复杂,在实现上很难做到,而且中断处理时系统工作的一部分,逻辑上不属于某一进程,不应被剥夺处理器资源。

2) 进程在操作系统内核程序临界区中:进入临界区后,需要独占式的访问共享数据,理论上必须加锁,以防止其他并行程序的进入,在解锁前不应该切换到其他进程,以加快该共享数据的释放。

3) 其他需要完全屏蔽中断的原子操作过程中:如加锁、解锁、中断现场保护、恢复等等源自操作。在原子过程中,连中断都要屏蔽,更不应该进行进程的切换。

如果在上述过程中发生了引起调度的条件,并不能马上进行调度和切换,应置系统请求调度标志,知道上述过程结束后才能进行相应的调度和切换。

应该进行进程的调度与切换的情况有:

1) 当发生引起调度条件且当前进程无法继续运行下去时,可以马上进行调度与切换。如果操作系统只在这种情况下进行进程调度,就是非剥夺调度。

2) 当中断处理结束后或自陷处理结束后,返回被中断进程的用户态程序执行现场前,若置上请求调度标志,即可马上进行进程调度与切换。如果操作系统支持这种情况下的运行调度程序,就实现了剥夺方式的调度。

进程切换往往在调度完成后立刻发生,它要求保存源进程当前切换点的进程信息,恢复被调度进程的现场信息。现场切换时,操作系统内核将源近程的现场信息推入到当前进程的内核堆栈来保存它们,并更新堆栈指针。内核完成从新进程的内核栈中装入新进程的线程信息、更新当前运行进程空间指针、重设PC寄存器等相关工作之后,开始运行新的进程。


分配处理机(Distributed Process, PD)意思是把某一种类型的资源分配给多个用户使用。这样做的目的是为了满足多个用户同时使用计算机的需求,并且使每个用户都能够得到最合适的处理机资源。
通常情况下,分配处理机资源的方法是将处理机资源按照优先级高低进行划分,并且根据每个用户的需求来确定需要多少处理机资源。例如,如果一个用户有很多作业需要处理,而这个用户只有一个 CPU,那么可以将这个用户的 CPU划分为多个单元,每个单元使用一台处理机。这样,每个用户都可以得到最适合自己需求的处理机资源。

调度的方式

所谓进程调度方式是指当某一个进程正在处理器上执行时,若有某个更为重要或紧迫的进程需要处理,既有优先权更高的进程进入就绪队列,此时应如何分配处理器。通常有一下两种进程调度方式:

(1) 非剥夺调度方式

非剥夺调度方式又称为非抢占调度方式,是指当一个进程正在处理器上执行时,即使有某个更为重要或紧迫的进程进入就绪状态,仍然让正在执行的进程继续执行,知道该进程完成或发生某种时间而进入阻塞状态时,才把处理器分配给更为重要或紧迫的进程。

(2) 剥夺调度方式

剥夺调度方式又称为抢占方式,是指当一个进程正在处理器上执行时,若有某个更为重要或紧迫的进程需要使用处理器,则立即暂停正在执行的进程,将处理器分配给这个更为重要或紧迫的进程。

“剥夺”不是一种任意性行为,必须遵循一定的原则:优先权原则,短进程优先原则和时间片原则。

3.调度器(调度程序scheduler)和闲逛进程


闲逛进程的存在是为了防止出现所有进程均处于阻塞态导致cpu无进程可以运行的情况出现。当系统中除闲逛进程外的所有进程均阻塞,就会调度闲逛进程运行,并在运行过程中一直测试中断。闲逛进程的优先级最低,一旦有其他进程从阻塞态进入就绪态,就暂停闲逛进程,调度该进程运行。


4.调度算法的评价指标(准则)

不同的调度算法具有不同的特性,在选择调度算法时,必须考虑算法所具有的特性。为了比较处理器调度算法的性能,人们提出很多评价准则,下面介绍主要的几种准则:

(1) CPU利用率

CPU是计算机系统中最重要的资源之一,所以应尽可能使CPU保持在忙状态,是这一资源利用率最高。

(2) 系统吞吐量

系统吞吐量表示单位时间内CPU完成作业的数量。长作业需要消耗较长的处理器时间,因此会降低系统的吞吐量。而对于短作业,他们所需要消耗的处理器时间端,因此能提高系统的吞吐量。调度算法和方式的不同,也会对系统的吞吐量产生较大的影响。

(3) 周转时间

周转时间是指从作业提交到作业完成所经历的时间,包括作业等待、在就绪队列中排队、在处理器上运行以及进行输入输出操作所花费的时间的总和。

作业的周转时间=作业完成时间-作业提交时间

(4) 等待时间

等待时间是指进程处于等处理器状态时间之和,等待时间越长,用户满意度越低。处理器调度算法实际上并不影响作业执行或输入输出操作时间,只影响作业在就绪队列中等待所花的时间。因此,衡量一个调度算法优劣常常只需简单地考察等待时间。

(5) 响应时间

响应时间是指从用户提交请求到系统首次产生响应所有的时间。在交互式系统中,周转时间不可能是最好的评测准则,一般采用响应时间作为衡量调度算法的重要准则之一。从用户的角度来看,调度策略应尽量降低响应时间,使响应时间处在用户能够接受的范围之内。

5.调度算法

处理调度(CPU调度)

定义:其任务是控制、协调作业进程对CPU的竞争,即按一定的调度算法,从输入井(就绪队列)中选择一个作业(进程),把CPU的使用权交给被选中的作业(进程)

通常系统的设计目标不同,所采用的调度算法也不同。在操作系统中存在多种调度算法,其中有的调度算法适用于作业调度,有的调度算法适用于进程调度,有的调度算法两者都适用。下面介绍几种常用的调度算法:

(1) FIFS先来先服务调度算法

特点:算法简单,但是效率低;有利于长作业,不利于短作业;有利于CPU繁忙型作业而不利于IO繁忙型作业。

饥饿和阻塞都是进程同步与调度中的概念,但它们的含义和表现方式略有不同。
饥饿(Starvation)
饥饿是指某个进程无法获取其所需的资源,导致该进程一直处于等待状态,无法继续执行。这种情况下,进程不会被挂起或阻塞,但它会一直等待,直到资源变得可用为止。饥饿通常是由于资源分配策略不当或者优先级设置不当引起的。
阻塞(Blocking)
阻塞是指进程在等待某个事件发生时被挂起,直到事件发生后才能继续执行。阻塞通常是由于进程需要等待某个资源变得可用或者需要等待某个操作完成而引起的。在阻塞状态下,进程会被挂起,不会占用CPU资源。
总之,饥饿和阻塞都是进程同步与调度中的重要概念,但它们的含义和表现方式略有不同。阻塞通常是由于等待某个资源或事件发生而引起的,而饥饿则是由于无法获取所需资源而导致的等待。

(2) SJF短作业优先调度算法

短作业(进程)优先调度算法是指对短作业和短进程优先调度的算法。短作业优先调度算法是从后备队列中选择一个或若干个估计运算时间最短的作业,将它们调入内存运行。

SJF调度算法的缺点:

1) 该算法对长作业不理。

2) 该算法完全未考虑作业的紧迫程度。

3) 由于作业的长短只根据用户所提供的估计执行时间而定的,而用户又可能会有意或无意的缩短其作业的估计运行时间,致使该算法不一定能真正做到算作业优先调度。

4) 注意:SJF调度算法的平均等待时间、平均周转时间最少。

(3) 高响应比优先调度算法

高响应比优先调度算法主要用于作业调度。同时考虑从每个作业的等待时间和估计需要运行的时间。

(4) 时间片轮转调度算法

时间片轮转调度算法主要适用于分时系统。

(5) 优先级调度算法

(6) 多级反馈队列调度算法

多级反馈队列调度算法主要是时间片轮转调度算法和优先级调度算法的综合和发展。通过动态调整进程优先级和时间片大小,多级反馈队列调度算法可以兼顾多方面的系统目标。

三、进程间通信(IPC, Inter-Process Communication

进程通信就是进程之间的数据交换。PV操作是低级通信方式,高级通信方式是指以较高的效率传输大量数据的通信方式。高级通信方法可分为共享存储、消息传递和管道通信三大通信方式。

消息缓冲


缓冲区是一块大的内存区域,用于存放代码和数据。而消息队列是一种数据结构,它存储了需要发送给其他程序的消息,并将其发送到系统缓冲区中。缓冲区分为三大类:全缓冲、行缓冲、无缓冲
全缓冲;只有在缓冲区被填满之后才会进行I/O操作;最典型的全缓冲就是对磁盘文件的读写。
行缓冲;只有在输入或者是输出中遇到换行符的时候才会进行I/O操作;这忠允许我们一次写一个字符,但是只有在写完一行之后才做I/O操作。一般来说,标准输入流(stdin)和标准输出流(stdout)是行缓冲。
无缓冲;标准I/O不缓存字符;其中表现最明显的就是标准错误输出流(stderr),这使得出错信息尽快的返回给用户。
消息队列包括一系列的操作:
1. 从系统缓冲区中读取消息
2. 将消息存储到消息队列中
3. 发送消息并监听系统缓冲区
4. 从消息队列中获取消息并将其放入自己的缓冲区
这就是消息队列的全部功能。
消息队列(Message Queue,简称MQ),指保存消息的一个容器,本质是个队列(FIFO,先进先出)。消息队列是一种异步的服务间通信方式,适用于无服务器和微服务架构。消息在被处理和删除之前一直存储在队列上。每条消息仅可被一位用户处理一次。

(1) 共享存储

在通信的进程之间存在着一块可以直接访问的共享空间,通过对这块共享空间的读写操作时间进程之间的信息交换。在共享存储方法中,需要使用同步互斥工具。

需要注意的是:用户进程空间一般都是相互独立的,要想让两个用户进程共享空间,必须通过特殊系统调用实现,而进程内的线程是自然共享进程空间的。

(2) 消息传递

消息队列和消息邮箱的不同就于消息队列可以认为是消息邮箱多次的发送,消息按FIFO或LIFO的方式存储而邮箱的话就这一次的发送会将上一次的发送覆盖掉,不具备FIFO的特性

(3) 管道通信


管道通信是消息传递的一种特殊方式。所谓管道,就是用于连接一个读进程和一个写进程以实现他们之间通信的一个共享文件,又名为pipe文件。向管道或共享文件提供输入的发送进程,以字符流的形式将大量的数据送入写管道;而接收管道输出的接收进程,则从管道中接受数据。为了协调双方的通信,管道机制必须它提供以下三方面的协调能力:互斥、同步和确定对方存在。

写进程往管道写数据,即便管道没被写满,只要管道没空,读进程就可以从管道读数据读进程从管道读数据,即便管道没被读空,只要管道没满,写进程就可以往管道写数据
无名管道(Pipe)和有名管道(Named Pipe)都是进程间通信的一种方式。它们之间的区别如下:
名称:无名管道是没有磁盘上的文件名的,只是一个内存中的缓冲区,所以也称为匿名管道;有名管道则是一个磁盘上的文件,在文件系统中有唯一的文件名。
进程关系:无名管道只能在具有亲缘关系的进程之间使用,如父子进程、兄弟进程等;而有名管道可以在不同进程之间进行通信,不需要进程之间有亲缘关系。
双向性:无名管道是一种半双工的通信方式,只能在一个方向上传输数据;而有名管道是一种全双工的通信方式,可以在两个方向上传输数据。
数据持久性:无名管道的数据只能在管道中传递,不会被保存到磁盘上,进程结束后数据就会消失;而有名管道的数据会被保存到磁盘上,可以被多个进程共享。
缓冲区大小:无名管道的缓冲区大小是固定的,一般为4KB;而有名管道的缓冲区大小可以通过系统调用来设置。
综上所述,无名管道和有名管道都是进程间通信的一种方式,它们之间的区别主要在于名称、进程关系、双向性、数据持久性和缓冲区大小等方面。开发人员需要根据具体需求选择合适的通信方式。
有名管道可以全双工通信的原因是因为它是基于文件的通信方式,可以通过文件描述符进行读写操作,实现数据的双向传输。在有名管道中,进程可以通过打开同一个文件来获取相同的文件描述符,从而进行通信。对于一个进程而言,它可以同时打开同一个管道的两个文件描述符,一个用于读取,一个用于写入,这样就可以实现双向传输的效果。
具体来说,如果一个进程打开了同一个有名管道的两个文件描述符,一个用于读数据,一个用于写数据。当进程向管道中写入数据时,数据就会被发送到管道的缓冲区中,当另一个进程从管道中读取数据时,数据就会从管道的缓冲区中被读取出来。因此,有名管道可以实现双向数据传输的效果。
需要注意的是,在使用有名管道进行全双工通信时,进程需要协同工作,以避免读写操作的冲突。如果两个进程同时读写同一个管道,就可能会出现数据的覆盖和混淆等问题,因此需要对管道的读写操作进行同步和互斥处理。

*快速面经

一、进程和线程的区别?

Ⅰ 拥有资源

进程是资源分配的基本单位,但是线程不拥有资源,线程可以访问隶属进程的资源。

Ⅱ 调度

线程是独立调度的基本单位,在同一进程中,线程的切换不会引起进程切换,从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。

Ⅲ 系统开销

由于创建或撤销进程时,系统都要为之分配或回收资源,如内存空间、I/O 设备等,所付出的开销远大于创建或撤销线程时的开销。类似地,在进行进程切换时,涉及当前执行进程 CPU 环境的保存及新调度进程 CPU 环境的设置,而线程切换时只需保存和设置少量寄存器内容,开销很小。

Ⅳ 通信方面

线程间可以通过直接读写同一进程中的数据进行通信,但是进程通信需要借助 IPC。

二、进程状态的切换

  • 就绪状态(ready):等待被调度

  • 运行状态(running)

  • 阻塞状态(waiting):等待资源

    只有就绪态和运行态可以相互转换,其它的都是单向转换。就绪状态的进程通过调度算法从而获得 CPU 时间,转为运行状态;而运行状态的进程,在分配给它的 CPU 时间片用完之后就会转为就绪状态,等待下一次调度。

    阻塞状态是缺少需要的资源从而由运行状态转换而来,但是该资源不包括 CPU 时间,缺少 CPU 时间会从运行态转换为就绪态。

三、进程调度算法

不同环境的调度算法目标不同

1. 批处理系统

批处理系统没有太多的用户操作,在该系统中,调度算法目标是保证吞吐量和周转时间(从提交到终止的时间)。

1.1 先来先服务 first-come first-serverd(FCFS)

非抢占式的调度算法,按照请求的顺序进行调度。

有利于长作业,但不利于短作业,因为短作业必须一直等待前面的长作业执行完毕才能执行,而长作业又需要执行很长时间,造成了短作业等待时间过长。

1.2 短作业优先 shortest job first(SJF)

非抢占式的调度算法,按估计运行时间最短的顺序进行调度。

长作业有可能会饿死,处于一直等待短作业执行完毕的状态。因为如果一直有短作业到来,那么长作业永远得不到调度。

1.3 最短剩余时间优先 shortest remaining time next(SRTN)

最短作业优先的抢占式版本,按剩余运行时间的顺序进行调度。 当一个新的作业到达时,其整个运行时间与当前进程的剩余时间作比较。如果新的进程需要的时间更少,则挂起当前进程,运行新的进程。否则新的进程等待。

2. 交互式系统

交互式系统有大量的用户交互操作,在该系统中调度算法的目标是快速地进行响应。

2.1 时间片轮转

将所有就绪进程按 FCFS 的原则排成一个队列,每次调度时,把 CPU 时间分配给队首进程,该进程可以执行一个时间片。当时间片用完时,由计时器发出时钟中断,调度程序便停止该进程的执行,并将它送往就绪队列的末尾,同时继续把 CPU 时间分配给队首的进程。

时间片轮转算法的效率和时间片的大小有很大关系:

  • 因为进程切换都要保存进程的信息并且载入新进程的信息,如果时间片太小,会导致进程切换得太频繁,在进程切换上就会花过多时间。

  • 而如果时间片过长,那么实时性就不能得到保证。

2.2 优先级调度

为每个进程分配一个优先级,按优先级进行调度。

为了防止低优先级的进程永远等不到调度,可以随着时间的推移增加等待进程的优先级。

2.3 多级反馈队列

一个进程需要执行 100 个时间片,如果采用时间片轮转调度算法,那么需要交换 100 次。

多级队列是为这种需要连续执行多个时间片的进程考虑,它设置了多个队列,每个队列时间片大小都不同,例如 1,2,4,8,..。进程在第一个队列没执行完,就会被移到下一个队列。这种方式下,之前的进程只需要交换 7 次。

每个队列优先权也不同,最上面的优先权最高。因此只有上一个队列没有进程在排队,才能调度当前队列上的进程。

可以将这种调度算法看成是时间片轮转调度算法和优先级调度算法的结合。

3. 实时系统

实时系统要求一个请求在一个确定时间内得到响应。

分为硬实时和软实时,前者必须满足绝对的截止时间,后者可以容忍一定的超时。

四、进程间通信

进程同步与进程通信很容易混淆,它们的区别在于:

  • 进程同步:控制多个进程按一定顺序执行;

  • 进程通信:进程间传输信息。

进程通信是一种手段,而进程同步是一种目的。也可以说,为了能够达到进程同步的目的,需要让进程进行通信,传输一些进程同步所需要的信息

管道:管道是通过调用 pipe 函数创建的,fd[0] 用于读,fd[1] 用于写。

它具有以下限制:

  • 只支持半双工通信(单向交替传输);

  • 只能在父子进程或者兄弟进程中使用。

FIFO:也称为命名管道,去除了管道只能在父子进程中使用的限制。FIFO 常用于客户-服务器应用程序中,FIFO 用作汇聚点,在客户进程和服务器进程之间传递数据。

消息队列:相比于 FIFO,消息队列具有以下优点:

  • 消息队列可以独立于读写进程存在,从而避免了 FIFO 中同步管道的打开和关闭时可能产生的困难;

  • 避免了 FIFO 的同步阻塞问题,不需要进程自己提供同步方法;

  • 读进程可以根据消息类型有选择地接收消息,而不像 FIFO 那样只能默认地接收

信号量:它是一个计数器,用于为多个进程提供对共享数据对象的访问

共享存储:允许多个进程共享一个给定的存储区。因为数据不需要在进程之间复制,所以这是最快的一种 IPC。

需要使用信号量用来同步对共享存储的访问。

多个进程可以将同一个文件映射到它们的地址空间从而实现共享内存。另外 XSI 共享内存不是使用文件,而是使用内存的匿名段。

套接字:与其它通信机制不同的是,它可用于不同机器间的进程通信。

优缺点

  • 管道:速度慢,容量有限;

  • Socket:任何进程间都能通讯,但速度慢;

  • 消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题;

  • 信号量:不能传递复杂消息,只能用来同步;

  • 共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存。


操作系统(三)——进程管理(上)的评论 (共 条)

分享到微博请遵守国家法律