OS 学习笔记 进程与线程

Posted 临风而眠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OS 学习笔记 进程与线程相关的知识,希望对你有一定的参考价值。

OS 学习笔记(8) 进程与线程

这篇笔记对应的王道OS 2.1 进程与线程

文章目录

2.1_1 进程的概念、组成、特征

知识总览

  • 进程
    • 概念:进程和程序的区别
    • 组成:一个进程由哪些部分组成
    • 特征:进程有哪些重要特征

为什么要引入进程

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

进程VS程序

  • 程序是静态的,是存放在磁盘里的可执行文件,如QQ.exe

  • 进程是动态的,是程序的一次执行过程,如:可多次启动QQ程序

  • 同一个程序多次执行对应多个进程

    打开任务管理器可以直观看到

操作系统怎么区分各个进程👇

进程的组成

PCB

  • 当进程被创建时,操作系统会为该进程 分配一个唯一的、不重复的“身份证 号”——PID(Process ID,进程ID)

  • 操作系统记录的一些信息

    • 操作系统要记录PID、进程所属用户ID(UID)

      👆 基本的进程描述信息,可以让操作系统区分各个进程

    • 操作系统还要记录给进程分配了哪些资源(如:分配了多少内存、正在使用哪些I/O设备、正在使用哪些文件)

      👆 可用于实现操作系统对资源的管理

    • 操作系统还要记录进程的运行情况(如:CPU使用时间、磁盘使用情况、网络流量使用情况等)

      👆 可用于实现操作系统对进程的控制、调度

  • 这些信息都被保存在一个数据结构**PCB (Process Control Block)** 中,即进程控制块 操作系统需要对各个并发运行的进程进行管理,但凡管理时所需要的信息,都会被放在PCB中

    为了使参与并发执行的每个程序(含数据)都能独立地运行, 必须为之配置一个专门的数据
    结构,称为进程控制块(Process Control Block,PCB)

程序段、数据段

  • PCB 是给操作系统用的。

  • 程序段、数据段是给进程自己用的。

  • 系统利用PCB来描述进程的基本情况和运行状态,进而控制和管理进程。

  • 相应地,由程序段、相关数据段和PCB三部分构成了进程实体(又称进程映像)

  • 所谓创建进程,实质上是创建进程实体中的PCB;而撤销进程,实质上是撤销进程的PCB。

  • 值得注意的是,进程实体/映像是静态的,进程则是动态的

    进程实体可以看作是运行过程中的快照

总结图

  • PCB是进程存在的唯一标志!

进程的定义

  • 定义
    • 进程是程序的一次执行过程
    • 进程是一个程序及其数据在处理机上顺序执行时所发生的活动
    • 进程是具有独立功能的程序在一个数据集合上运行的过程,是系统进行资源分配和调度的一个独立单位
    • 进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位

进程的特征

  • 动态性(进程最基本的特征)
  • 并发性
  • 独立性
  • 异步性
  • 结构性

知识回顾

引入线程后,进程就不再是接受调度的基本单位了,但是进程依然是获得资源的基本单位

2.1_2 进程的状态与转换、进程的组织

知识总览

进程的五种状态

状态解释
运行态Running该时刻进程占用CPU
就绪态Ready进程获得了除处理机外的一切所需资源,一旦得到处理机,就可以立即运行
阻塞态Blocked该进程正在等待某一事件发生而暂停运行,即使给他CPU控制权,它也无法运行
创建态New进程正在被创建时的状态
结束态Exit进程正在从系统中消失时的状态

创建态、就绪态

运行态

  • 当CPU空闲时,操作系统 就会选择一个就绪进程, 让它上处理机运行

  • 如果一个进程此时在CPU上运行,那么这个进程 处于“运行态”。 CPU会执行该进程对应的程序(执行指令序列)

阻塞态

  • 在进程运行的过程中,可能会请求等待某个事件的发生(如等待 某种系统资源的分配,或者等待其他进程的响应)。
  • 在这个事件发生之前,进程无法继续往下执行,此时操作系统会 让这个进程下CPU,并让它进入“阻塞态
  • 当CPU空闲时,又会选择另一个“就绪态”进程上CPU运行

  • 当等待的事件 发生时,进程 从“阻塞态” 回到“就绪态”

终止态

  • 一个进程可以执行 exit 系统调用,请求操作系统终止该进程。
  • 此时该进程会进入“终止态”,操作系统会让该进程下CPU, 并回收内存空间等资源,最后还要回收该进程的PCB。
  • 当终止进程的工作完成之后,这个进程就彻底消失了。

进程状态的转换

发生的情况及解释状态转换
进程被调度,获得处理机资源(分派处理机时间片)就绪态→运行态
时间片用完后,不得不让出处理机
可剥夺的OS中,当有更高优先级的进程就绪时,调度程序将正在执行的进程转换为就绪态,让更高优先级的进程执行
运行态→就绪态
进程请求某一资源(如外设) 的使用和分配时
等待某一事件的发送时(如I/O操作的完成)
进程以系统调用的方式请求OS提供服务,这个过程系统从用户态转换为核心态
该过程是主动行为
运行态→阻塞态
进程等待的事件到来时,如I/O操作结束或中断结束时
**该过程是被动行为**需要其他相关进程的协助
阻塞态→就绪态

进程的组织方式

进程PCB中,会有一个变量 state 来表示进程的当前状态。如:1表示创建态、2表示就绪态、3表示运行态… 为了对同一个状态下的各个进程进行统一的管理,操作系统会将各个进程的PCB组织起来。

组织方式
链接方式把统一状态的PCB链成一个队列,不同状态对应不同的队列
也可把处于阻塞态的进程的PCB,根据阻塞原因的不同,排成多个阻塞队列
索引方式将统一状态的进程组织在一个索引表中 ,索引表的表项指向相应的PCB
不同状态对应不同的索引表,如就绪索引表,阻塞索引表

链接方式

索引方式

知识回顾与重要考点

2.1_3 进程控制

知识总览

什么是进程控制

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

如何实现进程控制? 原语

为何需要“一气呵成”

  • 如果不能“一气呵成”,就有可能导致操作系 统中的某些关键数据结构信息不统一的情况, 这会影响操作系统进行别的管理工作

  • 例子如下图

如何实现原语的“原子性”

  • 原语的执行具有原子性,即执行过程只能一气呵成,期间不允许被中断。 可以用 “关中断指令”和“开中断指令”这两个特权指令实现原子性

  • 正常情况下

    CPU每执行完一条指令都会例 行检查是否有中断信号需要处理,如果有, 则暂停运行当前这段程序,转而执行相应 的中断处理程序。

  • CPU执行了关中断指令之后,就不再例行 检查中断信号,直到执行开中断指令之后 才会恢复检查。

  • 这样,关中断、开中断 之间的这些指令序 列就是不可被中断的,这就实现了“原子性”

进程控制相关的原语

进程的创建:创建原语

  • 允许一个进程创建另一个进程,此时创建者称为父进程,被创建的进程称为子进程。子进程可以继承父进程所拥有的资源。当子进程被撤销时,应将其从父进程那里获得的资源归还给父进程。此外,在撤销父进程时,通常也会同时撤销其所有的子进程。

  • 在操作系统中,终端用户登录系统、作业调度、系统提供服务、用户程序的应用请求等都会
    引起进程的创建。操作系统创建一个新进程的过程如下(创建原语):

    • 1)为新进程分配一个唯一的进程标识号,并申请一个空白PCB(PCB是有限的)。若PCB申请失败,则创建失败。

    • 2)为进程分配其运行所需的资源,如内存、文件、I/O设备和CPU时间等(在PCB中体现)。这些资源或从操作系统获得,或仅从其父进程获得。如果果资源不足(如内存),则并不是创建失败,而是处于创建态,等待内存资源。

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

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

进程的终止:撤销原语

进程的阻塞和唤醒:阻塞原语、唤醒原语

进程的切换:切换原语

  • 运行环境信息其实就是进程上下文(context)

  • 保存运行环境,恢复运行环境是实现并发的关键

    • 程序是很多条指令构成的,这些指令顺序执行 的过程中,很多中 间结果是放在各种 寄存器中的,比如说一个进程在执行完中间某条指令的时候,另一个进程开始上CPU运行,另一个进程在运 行过程中也会使用各个寄存器,会覆盖掉之前寄存器中的信息

    • 解决办法就是:在进程切换时先在PCB中保存这个进程的运行环境 (保存一些必要的寄存器信息)

    • 当原来的进程再次投入运行时,可以通过PCB恢复它的运行环境

知识回顾与重要考点

  • 进程控制会导致进程状态的转换。无论哪个进程控制原原语,要做的无非三类事情
    • 1.更新PCB中的信息
      • a.所有的进程控制原语一定都会修改进程状态标志
      • b.剥夺当前运行进程的CPU使用权必然需要保存其运行环境
      • c.某进程开始运行前必然要恢复期运行环境
    • 2.将PCB插入合适的队列
    • 3.分配/回收资源

2.1_4 进程通信(IPC)

知识总览

什么是进程间通信

  • 进程通信是指进程之间的信息(Inter-Process Communication, IPC)

进程通信的例子:知乎、B站分享到QQ、微信等

为什么进程通信需要操作系统支持?

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

  • 为了保证安全,一个进程不能直接访问另一个进程的地址空间

  • 所以肯定需要操作系统的支持,才能进程通信

共享存储

  • 在通信的进程之间存在一块可直接访问的共享空间,通过对这厂片共享空间进行写/读操作实现
    进程之间的信息交换。
  • 在对共享空间进行写/读操作时,需要使用同步互斥工具(如P操作、V操作),对共享空间的写/读进行控制。
  • 共享存储又分为两种:低级方式的共享是基于数据结构的共享:高级方式的共享则是基于存储区的共享。操作系统只负责为通信进程提供可共享使用的存储空间和同步互斥工具,而数据交换则由用户自己安排读/写指令完成。
  • 注意,进程空间一般都是独立的,进程运行期间一般不能访问其他进程的空间,想让两个进程共享空间,必须通过特殊的系统调用实现,而进程内的:线程是自然共享进程空间的。
  • 简单理解就是,甲和乙中间有一个大布袋,甲和乙交换物品是通过大布袋进行的,甲把物品放在大布袋里,乙拿走。但乙不能直接到甲的手中拿东西,甲也不能直接到乙的手中拿东西。

基于存储区的共享(高级)

  • 基于存储区的共享:操作系统在内存中划出一 块共享存储区,数据的形式、存放位置都由通 信进程控制,而不是操作系统。这种共享方式 内存速度很快,是一种高级通信方式

基于数据结构(低级)

  • 基于数据结构的共享:比如共享空间里只能放 一个长度为10的数组。这种共享方式速度慢、 限制多,是一种低级通信方式

消息传递

若通信的进程之间不存在可直接访问的共享空间,则必须利用操作系统提供的消息传递方法实现进程通信。进程通过系统提供的发送消息和接收消息两个原语进行数据交换。这种方式隐藏了通信实现细节,使通信过程对用户透明,简化了通信程序的设计,是当前应用最广泛的进程间通信机制。在微内核操作系统中,微内核与服务器之间的通信就采用了消息传递机制。由于该机制能很好地支持多处理机系统、分布式系统和计算机网络,因此也成为这些领域我最主要的通信工具。

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

格式化的消息如下图

直接通信方式

  • 直接通信方式。发送进程直接把消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中取得消息


间接(信箱)通信方式

  • 发送进程把消息发送到某个中间实体,接收进程从中间实体取得消息。
    这种中间实体一般称为信箱。该通信方式广泛应用于计算机网网络中



  • 简单理解就是,甲要告诉乙某些事情,就要写信,然后通过邮差送给乙。
    • 直接通信就是邮差把信直接送到乙的手上;
    • 间接通信就是乙家门口有一个邮箱,邮差把信放到邮箱里。

管道通信

  • 管道通信是消息传递的一种特殊方式

  • "管道"是一个特殊的共享文件,是指用于连接一个读进程和一个写进程以实现它们之间的通信的一个共享文件,又名pipe文件。其实就是在内存中开辟一个大小固定的内存。

    是一个循环队列

  • 向管道(共享文件)提供输入的发送进程(即写进程),以字符流形式将大量的数据送入(写)管道;而接收管道输出的接收进程(即读进程)则从管道中接收(读)数据。为了协调双方的通信,管道机制必须提供以下三方面的协调能力:互斥、同步和确定对方的存在。

  • 管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置 两个管道
  • 各进程要互斥地访问管道(由操作系统实现)
  • 管道写满时,写进程阻塞,直到读进程将管道中的数据取走,即可唤醒写进程。
  • 管道读空时,读进程阻塞,直到写进程往管道中写入数据,即可唤醒读进程。
  • 管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:①一个管道允许多个写进程,一个读进程(2014年408真题高教社官方答案);②允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux 的方案)。

知识回顾与重要考点

  • 王道书纠错

2.1_5 线程的概念

知识总览

什么是线程,为什么要引入线程?

  • 还没引入进程之前,系统中各个程序只能串行执行

  • 引入了进程之后,多道程序可以并发执行

    • 但是,进程是程序的 一次执行。但像QQ又要聊天,又要视频通话,又要传文件,这些功能显然 不可能是由一 个程序顺序处理就能实现的
  • 有的进程可能需要“同时”做很多事,而传统 的进程只能串行地执行一系列程序。为此,引入了“线程”,来增加并发度。

  • 传统的进程是程序执行流的最小单位,引入线程后,线程成为了程序执行流的最小单位

可以把线程理解为“轻量级进程”。

线程是一个基本的CPU执行单元, 也是程序执行流的最小单位

引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程也可以并发处理各种任务(如QQ 视频、文字聊天、传文件)

引入线程后,进程只作为除CPU之 外的系统资源的分配单元(如打印机、内存地址空间等都是分配 给进程的)。

线程则作为处理机的分配单元

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

  • 资源分配和调度方面

    • 传统进程机制中,进程是资源分配、调度的基本单位
    • 引入线程后,进程是资源分配的基本单位,线程是调度的基本单位
  • 并发性方面

    • 传统进程机制中,只能进程间并发
    • 引入线程后,各线程间也能并发,提升了并发度
  • 系统开销方面

    感觉王道给的图书馆看书的那个类比有点怪怪的…

    • 这里让chatgpt给我类比一下:
      • 切换进程状态:想象你正在做一个家务,比如洗碗,现在有一个紧急的电话需要你接,你就暂停洗碗去接电话,完成电话后回来继续洗碗。
      • 切换线程状态:想象你正在做一个家务,比如洗碗,你需要一把清洁剂,你就暂停洗碗去取清洁剂,然后回来继续洗碗。
    • 传统的进程间并发,需要切换进程的运行环境,系统开销很大
    • 线程间并发,如果是同一进程内的线程切换,则不需要切换进程环境,系统开销小
    • 引入线程后,并发所带来的系统开销减小

线程的属性

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

2.1_6 线程的实现方式、多线程模型

知识总览

线程的实现方式

用户级线程(User-Level Thread,ULT)

  • 历史背景:早期的操作系统(如:早期Unix)只支持进程, 不支持线程。当时的“线程”是由线程库实现的


    很多编程语言提供了强大的线程库,可以实现线程的创建、销毁、调度等功能。

  • 线程的管理工作由谁来完成?

    • 用户级线程由应用程序通过线程库实现, 所有的线程管理工作都由应用程序负责(包括线程切换)
  • 线程切换是否需要CPU转变状态?

    • 用户级线程中,线程切换可以在用户态下 即可完成,无需操作系统干预。
  • 操作系统是否能意识到用户级线程的存在?

    • 在用户看来,是有多个线程。但是在操作 系统内核看来,并意识不到线程的存在。 “用户级线程”就是“从用户视角看能的线程”
  • 这种线程的实现方式有什么优点和缺点

    • 优点:用户级线程的切换在用户空间即可完 成,不需要切换到核心态,线程管理的系统开销小,效率高
    • 缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可 在多核处理机上并行运行。

内核级线程(Kernel-Level Thread, KLT)

  • 线程的管理工作由谁来完成?
    • 操作系统内核完成
  • 线程切换是否需要CPU转变状态?
    • 线程调度、切换等工作都由内核负责,因 此内核级线程的切换必然需要在核心态下才 能完成
  • 操作系统是否能意识到内核级线程的存在?
    • 操作系统会为每个内核级线程建立相应的 TCB(Thread Control Block,线程控制块), 通过TCB对线程进行管理。 “内核级线程”就是“从操作系统内核视角看能的线程”
  • 这种线程的实现方式有什么优点和缺点
    • 优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核 处理机上并行执行。
    • 缺点:一个用户进程会占用多个内核级线程, 线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大

多线程模型

在支持内核级线程的系统中,根据 用户级线程和内核级线程的映射关 系,可以划分为几种多线程模型

一对一模型

  • 一对一模型:一个用户级线程映射到一个内 核级线程。每个用户进程有与用户级线程同 数量的内核级线程。
  • 优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核 处理机上并行执行。
  • 缺点:一个用户进程会占用多个内核级线程, 线程切换由操作系统内核完成,需要切换到 核心态,因此线程管理的成本高,开销大。

多对一模型

  • 多对一模型:多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程。
  • 优点:用户级线程的切换在用户空间即可完 成,不需要切换到核心态,线程管理的系统 开销小,效率高
  • 缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行

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

多对多模型

  • 多对多模型:n 用户及线程映射到 m 个内核级 线程(n >= m)。每个用户进程对应 m 个内核 级线程。
  • 克服了多对一模型并发度不高的缺点(一个阻 塞全体阻塞),又克服了一对一模型中一个用线程库户进程占用太多内核级线程,开销太大的缺点。

知识回顾与重要考点

  • 总结ULT和KLT

    • 可以这么理解:

      • 用户级线程是“代码逻辑”的载体

      • 内核级线程是“运行机会”的载体

        内核级线程才是处理机分配的单位.例如:多核 CPU环境下,左边这个进程最多能被分配两个核

      一段“代码逻辑”只有获得了“运行机会”才能被 CPU执行

      内核级线程中可以运行任意一个有映射关系的用户 级线程代码,只有两个内核级线程中正在运行的代 码逻辑都阻塞时,这个进程才会阻塞

2.1_7 线程的状态转换、线程的组织与控制

线程的状态转换

线程的组织与控制

  • (1)线程控制块
    与进程类似,系统也为每个线程配置一个线程控制块TCB,用于记录控制和管理线程的信息。线程控制块通常包括:
    • ①线程标识符;
    • ②一组寄存器,包括程序计数器、状态寄存器和通用寄存器;
    • ③线程运行状态,用于描述线程正处于何种状态;
    • ④优先级;
    • ⑤线程专有存储区,线程切换时用于保存现场等;
    • ⑥堆栈指针,用于过程调用时保存局部变量及返回地址等。
      同一进程中的所有线程都完全共享进程的地址空间和全局变量。各个线程都可以访问进程地址空间的每个单元,所以一个线程可以读、写或甚至清除另一个线程的堆栈。
  • (2)线程的创建
    • 线程也是具有生命期的,它由创建而产生,由调度而执行,由终止而消亡。相应地,在操作系统中就有用于创建线程和终止线程的函数(或系统调用)。
    • 用户程序启动时,通常仅有一个称为“初始化线程”的线程正在执行,其主要功能是用于创建新线程。在创建新线程时,需要利用一个线程创建函数,并提供相应的参数,如指向线程主程序的入口指针、堆栈的大小、线程优先级等。线程创建函数执行完后,将返回一个线程标识符。
  • (3)线程的终止
    • 当一个线程完成自己的任务后,或线程在运行中出现异常而要被强制终止时,由终止线程调用相应的函数执行终止操作。但是有些线程(主要是系统线程)一旦被建立,便一直运行而不会被终止。通常,线程被终止后并不立即释放它所占有的资源,只有当进程中的其他线程执行了分离函数后,被终止线程才与资源分离,此时的资源才能被其他线程利用。
    • 被终止但尚未释放资源的线程仍可被其他线程调用,以使被终止线程重新恢复运行。

类比进程:人的生命历程

王道书上这部分写的挺好


以上是关于OS 学习笔记 进程与线程的主要内容,如果未能解决你的问题,请参考以下文章

Python学习笔记(十五)

区分 Java 线程和 OS 线程?

Python学习笔记

Python学习笔记

java学习笔记之初识多线程

OS学习记录:线程