进程与线程

141 阅读18分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

进程的引入

进程与程序

进程是可并发执行的程序在一个数据集合上的执行过程。

程序是一个按顺序设计的计算机指令的集合,而进程就是执行这个指令集合的过程。程序是一个存放在计算机存储空间内的静态文件

单道程序的顺序执行

程序的顺序执行

1.顺序执行时操作的先后次序

顺序执行中,每个程序的执行顺序是严格按照次序先后关系进行的。例如:

2.程序段的执行

在单道环境中,程序段的执行也是严格按照顺序执行的。

顺序执行的特征

  1. 顺序性:程序在执行时,严格按照规定的顺序执行。
  2. 封闭性:程序是在封闭的环境中执行的,程序在执行时独占系统中的全部资源。
  3. 可再现性:当程序被重复执行时,只要初始条件相同,其执行结果必然相同。

应用:这些特征给测试和修改程序带来了很大的方便(debug)。

多道程序的并发执行

单道程序系统浪费资源、效率低下,现代操作系统几乎不采用,而广泛采用多道程序设计技术。多道程序设计是在内存中存放多道程序,他们在操作系统的控制下在CPU上交替执行。

程序的并发执行

为了提高计算机内各种资源的利用率,提高计算机系统的处理能力,并发处理技术得到广泛的应用。
而有些计算是允许并发执行的,有些操作是需要顺序执行的。
例如,下面两张图中,第一张图的计算是必须按照顺序执行的,而第二张图可以并发执行:

2.程序段的执行

3.并发执行的程序段

并发执行的条件 —— Bernstein

对于两个进程P1、P2,记P1的读集、写集分别为R(P1)、W(P1),P2的读集、写集为R(P2)、R(P2),若满足:R(P1)∩W(P2)∪R(P2)∩W(P1)∪W(P1)∩W(P2)={},则P1、P2可以并发执行且具有再现性。

范例:
对于:
P1: a=5
P2: b=6
P3: c=a+b
P4: d=c+1

的执行图如下:

P1

P3

p2

P4

P1: a=5
P2: b=6
R(P1)={} W(P1)={a}
R(P2)={} W(P2)={b}
R(P1) ∩W(P2)={} R(P2) ∩W(P1)={}
W(P1) ∩W(P2)={}
R(P1)∩W(P2)∪R(P2)∩W(P1)∪W(P1)∩W(P2)={}
P1、P2可以并发执行

P3: c=a+b
P4: d=c+1
R(P3)={a,b} W(P3)={c}
R(P4)={c} W(P4)={d}
R(P3) ∩ W(P4)={}
R(P4) ∩ W(P3)={c}
R(P3) ∩ W(P4) ∪ R(P4) ∩ W(P3) ∪ W(P3) ∩ W(P4) ={c}
P3、P4不能并发执行

程序并发执行的特征

  1. 间断性:进程之间需要相互配合,有时需要暂停等待另一个进程执行完毕才可以继续执行。
  2. 失去封闭性:多个程序共享系统的各种资源,这些资源的状态由多个程序改变,致使其失去封闭性。
  3. 失去可再现性:由于失去了封闭性,系统的资源状态的变化是不可预测的,因而也失去了可再现性。

进程与程序的对应关系

进程程序
动态的静态的
并发的顺序的
暂时的永久的

进程的数据结构 = 程序 + 数据 + PCB
程序与进程不是一一对应的关系,一个程序可以产生多个进程。

进程的状态及组成

进程的状态

进程的基本状态

进程有3种基本状态,按照分类有执行和未执行,其中执行是运行状态,未执行包括就绪阻塞状态。

  • 运行状态:进程正在处理机上运行的状态。
  • 就绪状态:已经获得了除处理机之外的所有必要的资源。当进程处于该状态时,只要获得了处理机资源,就是运行状态。
  • 阻塞状态:当进程由于等待输入或输出操作,或某个同步事件而暂停运行时的状态。

三种状态存在转换关系:

4.三种进程状态转换

创建状态和退出状态

许多操作系统中,除上述三种基本状态以外,还另外添加了创建状态和退出状态。

5.五种进程状态转换

创建状态的进程正在创建中,不能运行。在创建过程中,要做:

  • 为进程分配PCB结构,填写相关内容
  • 为进程分配进程组,连接进程的父子关系
  • 为进程分配所需的资源
  • 为进程建立地址空间,填写相关管理内存的操作,加载程序等

退出状态或异常结束,操作系统首先要将该进程从运行状态中移出,使之成为一个不可能再次运行的进程,即使其处于退出状态,并回收资源。
此时系统并不会立即撤销该进程,而是暂时留在系统中,以便让其他相关进程从该退出进程的PCB中收集有关信息。此外,还需要将退出代码传递给其父进程等。

进程的挂起

在一些操作系统中,对进程的状态增加了挂起状态。
挂起状态指的是将该进程存放至外存,在这种状态下,即使该进程等待的事件发生或者阻塞的原因解除,该挂起进程仍然不能进入就绪状态,因为它还在外存。
引入挂起状态由以下几个原因:

  1. 内外存对换的需要:为了缓和内存紧张的情况,将内存中处于阻塞状态的进程换至外存,这样进程又处于一种有别于阻塞状态的新状态。
  2. 用户调试程序的需要:用户在调试自己爹程序时,希望其运行的程序暂时停止下来,以便对进程的地址空间进行读写。
  3. 实时系统中调节负载的需要:当实时系统负载较重时,可能会影响到系统对实时任务的控制和处理,此时系统需要将不太重要或者不太紧急的进程进行挂起,以保证系统对紧急事件的及时处理。

6.双挂起进程状态转换

  1. 阻塞->️阻塞挂起:当内存紧张时会将处于阻塞状态的进程从内存移至内存(即挂起),可以腾出更多的空间给新创建的进程或就绪的进程。
  2. 就绪->就绪挂起:当挂起一些阻塞进程之后仍无法满足内存的需要,或者当有高优先级阻塞的进程或低优先级就绪的进程时,系统会选择首先挂起低优先级的进程。(因为系统应当让高优先级的进程尽快完成)
  3. 运行->就绪挂起:在抢占式分时操作系统中,当高优先级阻塞挂起的进程因事件出现而进入就绪挂起状态时,系统可能将正在运行的进程状态转化为就绪挂起状态。
  4. 就绪挂起->就绪:当系统没有就绪的进程或者当就绪挂起的进程优先级高于就绪的进程时,会引起这种转改的转换。
  5. 阻塞挂起->阻塞:当进程时放了足够的内存空间,系统会将高优先级阻塞挂起的进程激活,移至内存当中。

进程控制块

进程的组成

进程是由程序、数据、进程控制快(PCB)、栈四个部分组成的。

进程的活动是通过CPU上执行一系列程序和对相应数据进行操作来体现的,使用进程控制块来标识进程本身的特征、进程的状态、进程的调度信息以及对资源的占有情况等,同时,程序的执行通常设计用于跟踪过程调用和过程间参数传递的堆栈

PCB的作用

记录操作系统所需的用于描述进程情况及控制进程运行的全部信息,使一个多道程序环境下不能独立运行的程序成为一个能独立运行的基本单位,是一个能与其他进程并发执行的进程。

  • 在操作系统需要调度某进程时,要从该进程的PCB中查找其运行状态和优先级
  • 在调度某进程后,要根据PCB中所保存的处理机状态信息恢复运行的现场,并根据PCB中的程序和数据的内存地址找到该进程对应的程序和数据
  • 进程执行过程中,当需要和其他相互合作的进程过实现同步、通信或文件访问时,也需要访问PCB
  • 当进程因为某种原因暂停执行时,也要将其断点的处理机环境保存在PCB中

PCB的内容

  1. 进程描述信息

    1. 进程名:由创建者提供,通常是对应可执行程序的名字。
    2. 进程标识符:为了方便系统使用而设置。在操作系统中,一般都为进程分配一个唯一的整数,作为进程标识符。通常是一个进程的序号。
    3. 用户名:创建该进程的用户名字。
  2. 处理机状态信息

    1. 通用寄存器:当程序运行时用于暂存信息。
    2. 指令计数器:存放要访问的下一条指令的地址。
    3. 程序状态字(PSW)寄存器:包括程序执行时的状态信息,包括条件码、执行方式、中断允许位等。
    4. 栈指针:每个进程都有一个或多个与之相关的地址栈,用于存放进程对应程序的过程和系统调用参数及返回地址,栈指针指向该栈的栈顶。
  3. 进程调度信息

    1. 进程的状态:指明该进程所处的状态。
    2. 进程的优先级:表示该进程的优先级程度的一个整数,优先级越高先获得处理机。
    3. 运行统计信息:这些信息与所采用的进程调度算法有关,其中包括进程已执行事件、等待时间等。
    4. 进程阻塞的原因:记录进程引起阻塞的原因。
  4. 进程控制和资源占用信息

    1. 程序入口地址:进程对应程序和数据的地址,当进程被调度执行时,用于找到其程序和数据。
    2. 程序的外存地址:进程被调出时使用的地址。当内存空间紧张时,进程可能会被调出内存,当内存有空闲空间时会被重新调入。
    3. 进程同步及通信机制:进程在执行时,可能会和其他进程有同步关系或相互通信,进程使用的信号量、消息队列指针等都要存放在PCB中。
    4. 资源占用信息:列出除CPU外,进程所需要的全部资源及已经占用的资源情况。
    5. 链接指针:指出本进程所在队列中下一个进程的PCB地址。

进程控制块的组织

一个系统中的进程有许多,每个进程都有一个进程控制块,因此管理好PCB,就管理好了进程。进程控制块的管理目前常用的是链接方式,即把具有相同运行状态的进程的PCB链接在一起,形成一个运行队列、就绪队列、阻塞队列、空闲队列。

7.PCB链接队列

对于单处理机系统,处于运行状态的进程只有1个,即无法组成运行队列。在多处理机系统中,运行队列以优先级高低的顺序排列。
对于阻塞队列,由于不同的进程阻塞原因可能不同,按照阻塞原因链接队列,例如有打印机队列、等待输入队列等。
空闲队列是将系统中空闲的进程控制块结构组织起来,以便新进程创建时,为之分配进程控制块。

进程控制

进程控制的职能就是对系统中对全部进程实行有效的管理,其主要表现是对一个进程进行创建、撤销以及在某些进程状态之间的转换控制。

操作系统内核

核心态和用户态

为了防止操作系统及其关键的数据结构(如PCB等)受到用户有意无意的破坏,通常将处理机的执行状态分为核心态和用户态。

  • 核心态:又称为系统态,具有较高的特权,能执行一切命令,访问所有寄存器和存储区。
  • 用户态:具有较低特权的执行状态,只能执行规定的命令,访问指定的寄存器和存储区。

通常,操作系统运行在核心态,用户程序运行在用户态。因此用户程序无法访问到操作系统的区域,防止了用户程序对操作系统的破坏。

程序状态字(PSW)寄存器中有一位表示处理机的执行状态。当用户程序在需要系统服务而调用系统调用时,处理机的执行状态设置为核心态;当调用完成后,处理机的执行状态又会被重置为用户态。

内核与原语

操作系统采用层次结构,将操作系统分为若干个层次,每一层完成操作系统的一部分功能。
为了提高操作系统的运行效率,通常把一些与硬件紧密相关的模块放在仅靠硬件的层次上,并且常驻内存。这个部分被称为操作系统的内核。
内核是计算机硬件上扩充的第一层软件,操作系统需要对这部分软件进行保护。内核是使用原语实现的。
原语是由若干指令构成的,是用于完成一定功能的过程,但是原语是原子操作构成的,是一个不可分割的、不可中断操作。

在不同的操作系统中,内核的作用不尽相同,但是都包括以下三个基本功能:

  • 时钟管理:操作系统中许多活动都需要时钟。在分时系统基于时间片的进程调度中,每当时间片用完时,需要时钟管理产生终端信号,才能够重新调度进程。在实时操作系统中,截止时间的控制也需要时钟管理程序的控制。
  • 中断处理:终端时操作系统赖以活动的基础,各种类型的系统调用的实现、进程调度、设备操作完成等都需要通过中断的方法通知处理机。
  • 原语操作:原语操作可以完成操作系统中的一些基本功能,如进程控制、进程同步及常用的进程通信手段等。

进程家族树

进程控制的职责是对系统中的全部进程实行有效管理,其主要表现在对一个进程进行创建、撤销以及进程状态的转换控制。通常允许一个进程创建和控制另一个进程,前者称之为父进程,后者称之为子进程,以此类推可以得到一个进程的家族树。家族关系在PCB中有明确体现。

8.进程家族树

进程的创建和撤销

进程的创建

引起创建进程的事件:

  • 用户登录:在分时操作系统中,当有用户登录后,就为该用户建立一个进程,并把它投入到就绪队列。
  • 新作业进入系统:当新的作业进入系统时,操作系统需要为之分配资源并创建进程。
  • 提供服务:当运行状态的用户进程提出某种请求后,系统会专门创建一个进程来提供用户所需要的服务(例如打印服务请求)。
  • 应用请求:用户进程需要在自己的应用进程中创建子进程。

创建原语需要做的工作:

  1. 申请空白PCB。将创建者提供的有关信息填入PCB。
  2. 初始化进程描述信息。将进程名、进程标识符、建立父子关系、填写进程所属组、初始化处理机状态信息、初始化进程控制信息、分配初始优先级。
  3. 为进程分配资源、存储空间。子进程的资源可以从父进程中继承;若进程的程序不在内存中,则应将其从外存调入内存,并将有关信息填入PCB。
  4. 将新进程插入到就绪队列,等待调度。

进程的撤销

引起进程撤销的事件:

  • 进程正常结束。
  • 进程异常结束。
  • 外界干预,由进程意外的事件引起的进程终止(例如人为干预、父进程要求、父进程撤销等)。

撤销原语需要做的工作:

  1. 查找撤销进程的PCB。
  2. 若进程处于运行状态,予以终止,并进行调度,重新挑选其他进程运行。
  3. 若进程有子进程,予以终止,递归处理。防止进程脱离家族而无法控制。
  4. 归还资源。
  5. 从所在队列中移出。

进程的阻塞和唤醒

在进程执行过程中,常常会因为等待I/O操作完成或等待某个事件出现而进入阻塞状态。当事件完成后,进程会被唤醒进入就绪状态。

进程的阻塞与唤醒的事件

  • 请求系统服务,完成后唤醒。如请求打印机等。
  • 启动某种操作,完成后唤醒。如启动某个输入设备,只有当进程完成数据的输入之后,才能继续执行。
  • 新数据尚未到达,到达后唤醒。对于相互合作的进程,如果一个进程需要另一个进程的数据,而没能及时提供时,则会等待进程完成数据的提供。
  • 无新工作可做,有新任务分配后唤醒。

阻塞原语需要做的的工作

  1. 停止进程的执行。
  2. 修改PCB中进程的状态标识,将进程插入阻塞队。
  3. 重新调度,挑选一个就绪的进程投入运行,并进行切换。

唤醒原语需要做的工作

  1. 将进程从阻塞队列解下。
  2. 把进程插入就绪队列。
  3. 改变进程PCB中的状态。

进程的挂起与激活

挂起原语要做的工作

  1. 检查被挂起进程的状态。
  2. 若处于就绪状态,将进程由就绪状态变为就绪挂起状态。
  3. 若处于阻塞状态,将进程由阻塞状态变为阻塞挂起状态。
  4. 若处于运行状态,将进程由运行状态变为就绪挂起状态,并调用进程调度程序重新调度。

线程

线程的概念

线程的引入

进程是一个可以拥有资源的独立单位,进程是一个可以独立调度和分派的基本单位。
由于进程是资源的拥有者,因此在进程的创建、撤销和切换中系统必须为之付出较大的时间、空间开销。所以系统中所设置的进程的数目不宜过多,进程切换的频率不宜过高。这就限制了进程并发程度的提高。

为了提高系统并发执行的程度,进一步提高系统的吞吐量,在20世纪80年代提出了线程的概念。
通过引入线程实现多线程,可以具有以下优点:

  • 响应度高:在交互式程序中,部分线程可以阻塞或执行较冗长的操作,另一部分线程继续执行,保证用户的响应时间
  • 资源共享:同一个进程的多个线程共享进程拥有的内存和资源
  • 经济:线程的创建和切换比进程更为经济

线程是进程的一个实体,是被独立调度和分派的基本单位,表示进程中的一个控制点,执行一系列指令。

9.进程线程关系

线程的组成

线程有时会被称为轻型进程(Light Weight Process, LWP),每个线程都有自己的线程控制块(Thread Control Block, TCB)。

TCB主要包括:

  • 线程标识符。
  • 描述处理机状态信息的一组寄存器。包括通用寄存器、指令计数器、程序状态字等。
  • 栈指针。每个线程都有用户栈和核心栈两个栈。当在用户态下运行时使用用户栈、在核心态下运行使用核心栈。
  • 一个私有的存储区。用于存放现场保护信息和其他与该线程相关的统计信息。

线程的状态

线程是一个动态过程,在一定条件下可以转换自己的状态。
通常,创建一个进程时,其主线程也会被创建,其他线程由主线程创建,,并提供对占空间,将新线程投入就绪队列。

当CPU空闲时,线程调度程序会从就绪队列中选择