【操作系统】进程与线程

142 阅读10分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第10天,点击查看活动详情

注意:下面标星*的表示会在以后补充

概念

Multiprogramming

什么是多道程序设计?
一种操作模式,由一个处理器交替执行两个或多个程序。

好处:提高CPU利用率。 通过允许多个程序“同时”驻留在主内存中,可以共享CPU,这样当一个程序启动I/O操作时,可以将另一个程序分配给CPU,从而提高CPU利用率。

多道程序设计的道数degree:同时加载到内存中的进程数称为多道程序设计的道数

concurrency并发

并发的好处:

  • 更好的资源利用率
    • 一个应用程序未使用的资源可以被其他应用程序使用。
  • 更好的平均响应时间
    • 无需等待其他应用程序完成。

进程

进程是运行程序的操作系统抽象。

进程与程序

进程与程序的关系:

  • 进程:正在执行的程序
  • 程序 = 静态文件
  • 进程 = 执行程序=程序+执行状态。
  • 进程是程序的实例。
  • 不同的进程可以运行同一程序的不同实例(如打开两个浏览器)

8个区别:

  1. 程序包含一组用于完成特定任务的指令。进程是正在执行的程序的实例
  2. 程序是一个消极实体,因为它驻留在辅助内存中。进程是一个活动实体,因为它是在执行期间创建并加载到主存中的。
  3. 程序存在于单个位置,并继续存在,直到被删除。进程存在的时间有限,因为它在任务完成后会被终止。
  4. 程序是一个静态实体。流程是一个动态实体。
  5. 程序不需要任何资源,它只需要存储指令的内存空间。进程对资源的要求很高,在其生命周期中需要CPU、内存地址、I/O等资源。
  6. 程序没有任何控制块。进程有自己的控制块,称为进程控制块
  7. 程序有两个逻辑组件:代码和数据。除了程序数据外,进程还需要管理和执行所需的其他信息。
  8. 程序本身不会改变。许多进程可以执行单个程序。它们的程序代码可能相同,但程序数据可能不同。

进程的创建和终止

进程创建事件:

  • 系统初始化
  • 执行进程创建系统调用
  • 创建新进程的用户请求
  • 批处理作业的启动

进程终止事件:
 Normal exit (voluntary)
 Error exit (voluntary)
 Fatal error (involuntary)
 Killed by another process (involuntary)

*进程的层次结构

进程的状态

三种状态:运行、就绪、阻塞 running, ready, block

  • running
    • 进程当前正在使用CPU。
  • ready
    • 当前正在等待分配给CPU。
    • 也就是说,进程可能正在运行,但另一个进程正在使用CPU,在等待另一个的进程
  • block
    • 进程正在等待事件,例如完成输入/输出、计时器关闭、资源可用等。

状态变化:

  • 运行->阻塞: 进程发现它无法继续。
  • 运行->就绪:就绪->运行: 由process scheduler引起。
  • 阻塞->-就绪: 进程正在等待的外部事件发生。

进程的实现

进程控制块(PCB,Process Control Block)

也叫做进程表项,是操作系统内核中的一种数据结构,包含管理特定进程所需的信息,OS为每个进程维护一个PCB,PCB由整数进程ID标识

PCB在一个进程的整个生命周期内保持不变,一旦进程终止,PCB就会被删除。 PCB的体系结构完全依赖于操作系统,在不同的操作系统中可能包含不同的信息。

PCB包含的信息: 进程ID 操作系统中每个进程的唯一标识。 状态 进程的当前状态。 指针 指向父进程的指针。 优先事项 流程的优先级。 程序计数器 CPU寄存器 各种CPU寄存器,其中需要存储进程以执行运行状态。 输入/输出信息 输入/输出状态信息包括分配给进程的输入/输出设备列表。Account信息 这包括用于进程执行的CPU数量、时间限制等。

image.png

状态队列

操作系统维护一组队列,这些队列表示系统中所有进程的状态。

  • 每个状态通常有一个队列,例如Ready队列,等待IO队列。
  • PCB根据目前状态排到对应状态队列当中
  • 当进程改变状态时,其PCB将从一个队列中断开链接,并链接到另一个队列。

PCB和状态队列:

  • PCB是数据结构,在操作系统内存中动态分配。
  • 创建进程时,将为其分配一个PCB,对其进行初始化,并将其放置在正确的队列中。
  • 随着进程的计算,其PCB从一个队列移动到另一个队列。
  • 当进程终止时,其PCB被释放。

进程表

进程表或PCB表:

  • OS维护一个进程表,每个条目都是PCB。
  • PCB表的大小决定了系统的并发度。
  • 两种组织形式:Link Index

image.png

进程的结构

  • User Code
  • User Data
  • User Stack: Used for procedure call and parameter passing.
  • PCB (Metadata)

image.png

上下文切换 Context Switch

将CPU从一个进程切换到另一个进程,由调度器执行。

image.png 过程:

  • 保存旧进程的PCB状态;
  • 加载新进程的PCB状态;
  • 刷新内存缓存;
  • 更改内存映射(TLB);

开销较大,且需要硬件支持

线程

一个进程希望进行不同活动,并共享内存

定义:进程内的顺序执行流 A sequential execution stream within a process(也称为轻量级进程)。

特性:

  • 进程中的所有线程共享相同的地址空间和操作系统资源
  • 线程共享内存,因此可以直接通信
  • 每个线程都有自己的栈(局部变量)、CPU寄存器、PC等。

image.png 优势:

  • 响应性
    • 多线程交互应用程序允许程序继续运行,即使部分程序被阻止或执行冗长的操作。
  • 资源共享
    • 同一进程中的线程可以更方便、更高效地共享数据和其他资源(无需复制或消息)。
    • 进程内的线程彼此不受保护(线程来自同一个进程,因此不存在不同用户之间)
  • 经济:线程比进程更轻。
    • 创建一个线程比一个进程便宜(大约10-20倍)。
    • 在同一进程中切换到不同的线程更便宜(5-50倍)。
  • 可扩展性
    • 更好地利用多处理器体系结构。 左边代表一个进程中线程共享的内容,右边代表每个线程独有的内容

image.png

阻塞和非阻塞调用:

  • 阻塞系统调用
    • 通常与I/O相关:read()、fread()、getc()、write()
    • 直到呼叫完成才返回。
    • 进程/线程切换到阻塞状态。
    • 当I/O完成时,进程/线程准备就绪。
  • 使用非阻塞系统调用进行I/O
    • 异步输入/输出
    • 复杂的
    • 一旦I/O启动,调用方将返回,并继续。
    • 一旦输入/输出完成,就会向调用者发送一个中断。

线程的实现

线程状态同进程,包含运行。就绪、阻塞,切换也相同

线程控制块(TCB)基本同PCB,线程表基本同进程表

不同点:

  • 线程:处理器状态
  • 进程:地址空间和操作系统资源(打开的文件等),没有执行状态

上下文切换: 在块内切换线程是一种简单的线程切换。 跨块切换线程需要更改内存和I/O地址表,更改地址空间,可能使缓存无效

TCB现在是上下文开关的单元。

  • 就绪队列、等待队列等现在包含指向TCB的指针。
  • 上下文切换导致CPU状态复制到TCB或从TCB复制CPU状态。

线程和进程

相同点:

  • 线程共享CPU,一次只运行一个线程。
  • 进程内的线程也按顺序执行。
  • 线程可以创建子线程。
  • 线程可以处于以下几种状态之一:运行、就绪或阻塞。
  • 线程也有程序计数器、堆栈、寄存器和状态

不同点:

  • 进程
    • 与单个程序的执行有关的资源所有权单位 Unit of resource ownership
    • 可以包含多个执行线程。
    • 进程在很大程度上是独立的,而且可能来自于不同用户,有保护机制
    • 昂贵的创建。
    • 昂贵的上下文切换。
  • 线程
    • Unit of execution
    • 属于进程。
    • 线程是同一“job”的一部分,并且积极而密切地协作。
    • 廉价创建
    • 廉价的上下文切换。

*POSIX线程

用户级线程 User-level Threads

  • 为了使线程既便宜又快速,它们需要在用户级别实现。
    • 用户级线程完全由运行时系统(线程库)管理
  • 用户级线程小而快。
    • 线程仅由PC、寄存器、堆栈和小型线程控制块(TCB)表示。
    • 通过过程调用创建新线程、在线程之间切换和同步线程。
    • 没有内核参与。
    • 用户级线程操作比内核线程快100倍。
  • 所有操作(创建、销毁、屈服yield)都是正常的过程调用(procedure calls)

用户级线程的优点

  • ULTs可以在任何操作系统上运行。
    • 只需要一个线程库。
  • ULT创建和管理速度很快。
  • 线程上下文切换比进程上下文切换快得多
    • 不需要内核模式开关。
    • 仅保存/加载寄存器。
    • 线程可能会自动产生(本地调用)。
  • 在用户级线程中,调度可以是特定于应用程序的。
    • 可能支持每个进程定制的调度算法。
  • 更好的可扩展性。

用户级线程的问题:

  • 大多数系统调用都是阻塞的,内核会阻塞进程。如果一个用户级线程执行阻塞操作,则整个进程将被阻塞
  • 解决:
    • 1、可以将系统调用更改为所有非阻塞,需要重写操作系统大部分。
    • 2、提前告知调用是否会阻塞。需要重写系统调用库的部分。
  • 线程可能垄断CPU(进程中没有时钟中断)。
  • 内核只能将进程分配给处理器。而同一进程中的两个线程不能同时在两个处理器上运行。

内核级线程 Kernel-level Threads

OS直接管理(而不是由进程管理)的线程称为内核级线程或轻量级(lightweight)进程。

内核级线程的优点:

  • 如果进程中的一个线程被阻塞,内核可以调度同一进程的另一个线程。
  • 内核例程本身可以是多线程的。
  • 内核可以在SMP多处理器上的不同CPU上调度多个线程。

内核级线程的缺点:

  • 调度、创建和删除线程的速度比用户级线程
  • 在同一进程中,控制权从一个线程转移到另一个线程需要切换到内核的模式。
  • 操作系统必须随着线程数量的增加而扩展。
ULTsKLTs
内核级线程用户级线程的创建和管理速度更快。内核级线程的创建和管理速度较慢(因为操作系统本身参与导致)。
通过用户级的线程库实现。操作系统支持创建内核线程。
操作系统支持创建内核线程。内核级线程特定于操作系统。
无法由操作系统调度。可以由操作系统调度。
多线程应用程序无法利用多处理。内核例程本身可以是多线程的。

可以在多处理器中的不同处理器上调度相关的内核级线程。

混合实现

内核级线程和用户级线程的混合:m-to-n线程映射

  • 应用程序创建m个线程。
  • OS提供了n个内核线程池。
  • 一些内核级线程会被用户级线程多路复用