2.1 进程与线程
4254字约14分钟
2024-12-18
2.1.1 进程的概念和特征
程序:是 静态的 ,就是个存放在磁盘里的可执行文件,就是一系列的指令集合
进程(Process):是 动态的 ,是程序的一次执行过程
2.1.2 进程的组成
一个进程实体(进程映像)由 进程控制块(PCB) 、程序段 、数据段 组成
进程控制块(PCB)
进程控制块(PCB) 是进程存在的唯一标志,当进程被创建时,操作系统为其创建PCB,当进程结束时,会回收PCB
当进程被创建时,操作系统会为该进程分配一个 唯一的、不重复 的“身份证号”-PID(Process ID,进程ID)
操作系统要记录PID、进程所属用户ID(UID)、进程资源分配(如:内存,I/O设备、文件),进程运行情况(如:CPU使用时间,磁盘使用情况,网络流量使用情况)等
这些信息都被保存在一个数据结构 PCB(Process Control Block)中,即 进程控制块
程序段
程序的代码(指令序列)
数据段
运行过程中产生的各种数据(如:程序中定义的变量)
程序是如何运行的
常用寄存器
PSW:程序状态字寄存器
存储 CPU 的运行状态信息(用户态|内核态)
PC:程序计数器
存储当前正在执行的指令地址和下一条执行的指令地址
IR:指令寄存器
存储当前正在执行的指令
通用寄存器
其他一些必要信息
2.1.3 进程的状态与转换
创建态
运行态
阻塞态
终止态
进程是如何状态转换的
进程的状态总结
进程的组织
链接方式
按照进程状态将PCB分为多个队列
操作系统持有指向各个队列的指针
索引方式
根据进程状态的不同,建立几张索引表
操作系统持有指向各个索引表的指针
2.1.4 进程控制
进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。
如何实现进程控制
使用 ”原语“ 实现,原语的执行具有原子性,期间不允许被中断
原语的 ”原子性“
通过 关中断指令 和 开中断指令 这两个 特权指令 实现 原子性
中断机制
关中断指令
用于 禁用CPU响应中断请求,表示临时关闭中断系统,执行关中断指令后,CPU将不再响应外部中断信号,直到执行开中断指令。
作用:防止在关键代码执行过程被中断打断,确保指令的原子性。
开中断指令
用于 重新启用CPU响应中断请求,表示允许中断系统正常工作,执行开中断指令后,处理器会检查和响应外部中断信号。
作用:恢复对外部中断的响应
中断机制的工作流程
- 外设或内部模块产生中断信号
- 如果中断被启用(CPU处于 开中断状态),中断控制器将信号传递给CPU。
- CPU暂停当前任务,保存上下文,跳转到中断服务程序。
- 完成中断服务后,恢复上下文,继续执行被中断的任务。
CPU 会按程序的 指令序列 依次执行指令,每执行完一条指令都会例行检查是否有中断信号需要处理,如果有,则暂停运行当前程序,执行 关中断指令,转而执行中断程序,,等中断程序处理完之后,会执行 开中断指令,并且回到原来程序继续往下执行。
注意:在中断程序的执行过程中,不需要再例行检查中断信号了,因为已经执行 关中断指令 了,等待当前中断程序处理完之后,回到程序后,再次出现外部中断信号,则继续去执行中断程序。
2.1.5 进程通信
为什么需要进程通信?
进程是分配系统资源的单位(包括内存地址空间),每个进程都拥有独立的内存地址空间和资源。因此访问其他进程的数据是不可能的,为了实现进程之间的数据交换,他们必须通过进程通信机制来实现。
通信方式
共享存储(共享内存)
共享存储允许多个进程映射到同一块内存区域,从而直接访问和修改内存中的数据。
为避免出错,各个进程对共享空间的访问应该是互斥的,各个进程可使用操作系统内核提供的同步互斥工具(如P、V操作)
基于数据结构
比如共享空间里只能放一个长度为10的数组,这种共享方式速度慢、限制多,是一种低级通信方式
基于存储区
操作系统在内存中划出一块恭喜那个存储区,数据的形式、存放位置都由通信进程控制,而不是操作系统。这种共享方式速度很快,是一种高级通信方式。
消息队列
进程间的数据交换以 **格式化的消息(Message)**为单位。进程通过操作系统提供的“发送消息/接收消息”两个原语进行数据交换
直接通信方式
消息发送进程要指明接收进程的ID
在直接通信方式中,消息队列的发送者和接受者是直接连接的,即每个消息都由一个明确的发送者和接受者。消息的传递是点对点的,发送者将消息发送到接受者的消息队列,接受者从消息队列中取出消息。
特点:
点对点通信:每条消息只能由一个接受者接收
发送者和接收者明确,发送方和接收方需要显式的指定对方标识。
实时性强,接收方从消息队列中获取消息时,是直接与发送方对应的,通信较为直接和快速
使用场景:
- 请求-响应模式:例如,在客户端与服务器之间进行通信时,客户端发送请求消息,服务器返回响应消息,采用直接通信方式。
- 命令通知:例如,发送系统命令或操作指令给特定的进程或服务。
间接通信方式(信箱通信方式)
通过“信箱”间接地通信,因此又称“信息通信方式”
在间接通信方式中,消息并不直接从发送者传递到接收者,而是通过一个中间的消息队列或消息交换代理来转发。消息首先进入一个中介的消息队列,接收者从该中介队列中读取消息。发送者和接收者之间不需要直接对接,消息队列作为一个“中介”角色存在。
特点:
广播式通信:一条消息可以发送给多个接收者(取决于消息队列的设计)。
解耦性强:发送者与接收者之间不直接关联,发送者只需将消息放入消息队列,接收者从消息队列获取消息。这种方式使得发送者与接收者之间实现了解耦。
异步通信:发送者发送消息后不需要等待接收者的响应,接收者可以在任意时间处理消息,适合异步处理任务。
管道通信
管道只能采用 半双工通信,某一时间段内只能实现单向的传输。如果要实现 双向同时通信,则需要设置两个管道。
各进程要互斥地访问管道(由操作系统实现)。
当管道写满时,写进程将阻塞,知道读进程将管道中的数据取走,即可唤醒写进程。
当管道读空时,读进程将阻塞,知道写进程往管道中写入数据,即可唤醒读进程。
管道中的数据一旦被读出,就彻底消失。因此,当多个进程读同一个管道时,可能会错乱。对此,通常有两种解决方案:1. 一个管道允许多个写进程,一个读进程(2014408真题高教社官方答案);2. 允许有多个写进程,多个读进程,但系统会让各个读进程轮流从管道中读数据(Linux方案)
2.1.6 线程和多线程模型
1. 线程的基本概念
引入进程的目的是更好地使多道程序并发执行,提高资源利用率和系统吞吐量;
引入线程 (Threads)的目的则是减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。
线程最直接的理解就是 轻量级进程,它是 一个基本的CPU执行单元,也是程序执行流的最小单元,由 线程ID、程序计数器、寄存器 集合和堆栈组成。
线程是进程中的一个实体,是被系统 独立调度 和 分派 的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。
一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有 就绪、阻塞和运行 三种基本状态。
2. 进程和线程的比较
调度:
在传统的操作系统中,拥有资源和独立调度的基本单位都是进程,每次调度都要进行上下文切换,开销较大。
在引入线程的操作系统中,线程是独立调度的基本单位,而线程切换的代价远低于进程。
在同一进程中,线程的切换不会引起进程切换。但从一个进程中的线程切换到另一个进程中的线程时,会引起进程切换。
并发性
在引入线程的操作系统中,不仅进程之间可以并发执行,而且一个进程中的多个线程之间亦可并发执行,甚至不同进程中的线程也能并发执行,从而使操作系统具有更好的并发性,提高了系统资源的利用率和系统的吞吐量。
拥有资源
进程是系统中拥有资源的基本单位,而线程不拥有系统资源,但线程可以访问其隶属进程的系统资源,这主要表现在属于同一进程的所有线程都具有相同的地址空间。要知道,若线程也是拥有资源的单位,则切换线程就需要较大的时空开销,线程这个概念的提出就没有意义。
独立性
每个进程都拥有独立的地址空间和资源,除了共享全局变量,不允许其他进程访问。
某个进程中的线程对其他进程不可见。同一进程中的不同线程是为了提高并发性及进行相互之间的合作而创建的,它们共享进程的地址空间和资源。
系统开销
在创建或撤销进程时,系统都要为之分配或回收进程控制块 PCB 及其他资源, 如内存空间、I/O 设备等。
操作系统为此所付出的开销,明显大于创建或撤销线程时的开销。
进程切换时涉及进程上下文的切换,而线程切换时只需保存和设置少量寄存器内容,开销很小。
此外,由于同一进程内的多个线程共享进程的地址空间,因此这些线程之间的同步与通信非常容易实现,甚至无须操作系统的干预。
支持多处理器系统
对于传统单线程进程,不管有多少个 CPU,进程只能运行在一个 CPU 上。
对于多线程进程,可将进程中的多个线程分配到多个 CPU 上执行。
线程的属性
线程是一个轻型实体,它不拥有系统资源,但每个线程都应有一个唯一的标识符和一个线程控制块,线程控制块记录线程执行的寄存器和栈等现场状态。
不同的线程可以执行相同的程序,即同一个服务程序被不同的用户调用时,操作系统将它们创建成不同的线程。
同一进程中的各个线程共享该进程所拥有的资源。
线程是CPU的独立调度单位,多个线程是可以并发执行的。在单CPU的计算机系统中,各线程可交替地占用CPU,在多CPU的计算机系统中,各线程可同时占用不同的CPU,若各个CPU同时为一个进程内的各线程服务,则可缩短进程的处理时间。
一个线程被创建后,便开始了它的生命周期,直至终止。线程在生命周期内会经历阻塞态、就绪态和运行态等各种状态变化。
线程的实现方式
用户级线程
线程的管理工作由谁来完成?
线程切换是否需要 CPU 变态?
操作系统是否能意识到用户级线程的存在?
这种线程的实现方式有什么优点和缺点?
内核级线程
线程的管理工作由谁来完成?
线程切换是否需要 CPU 变态?
操作系统是否能意识到内核级线程的存在?
这种线程的实现方式有什么优点和缺点?