【操作系统基础】进程管理(一)进程与线程的描述与控制

一、进程的定义与特征

1. 进程的定义与特征

进程(Process)是资源分配的基本单位。进程是动态的,是程序的一次执行过程,同一个程序执行会对应多个进程。相反,程序是即是静态的,就是存放在磁盘里的可执行文件,就是一系列的指令集合。

2. 进程的组成

程序段、数据段、PCB三部分组成了进程的实体(进程映像),引入进程实体的概念后,可把进程定义为:进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。

2.1 PCB

当进程被创建时,操作系统会为该进程分配一个唯一的、不重复的“身份证号”——PID(Process ID)。操作系统要记录 PID、进程所属用户 ID(UID),还要记录给进程分配了哪些资源(如:分配了多少内存、正在使用哪些 I/O 设备),还要记录进程的运行情况(如:CPU 使用时间、磁盘使用情况等)。

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

PCB包括了一下四个方面的信息:

  • 进程描述信息:包括进程标识符PID、用户标识符UID;
  • 资源分配清单:正在使用哪些文件、正在使用哪些内存区域、正在使用哪些IO设备;
  • 进程控制和管理信息:正在使用哪些文件、正在使用哪些内存区域、正在使用哪些IO设备;
  • 进程控制和管理信息:CPU、磁盘、网络流量使用情况,进程当前状态(就绪态/阻塞态/运行态);
  • 处理机相关信息:如 PSW、PC 等等各种寄存器的值(用于实现进程切换)。
2.2 程序段、数据段

程序段是指程序的代码(指令序列),数据段是指运行过程中产生的各种数据(如:程序中定义的变量)。程序段、数据段是给进程自己用的,与进程自身的运行逻辑有关。

在这里插入图片描述

3. 进程的特征

程序是静态的,进程是动态的,相比于程序,进程拥有以下特征:

  1. 动态性:进程是程序的一次执行过程,是动态地产生、变化和消亡的
  2. 并发性:内存中有多个实体进程,各进程可并发执行
  3. 独立性:进程是能独立运行的、独立获得资源、独立接受调度的基本单位
  4. 异步性:各进程按各自独立的、不可预知的速度向前推进,操作系统要提供“进程同步机制”来解决异步问题
  5. 结构性:每个进程都会配置一个 PCB。结构上看,进程由程序段、数据段、PCB 组成。

二、进程的状态切换

在这里插入图片描述

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

需要注意的是:

  1. 阻塞态→就绪态不是进程自身能控制的,是一种被动行为
  2. 运行态→阻塞态是一种进程自身做出的主动行为
  3. 不能由阻塞态直接转换成运行态,也不能由就绪态直接转换为阻塞态(因为进入阻塞态是进程主动请求的,必然需要进程在运行时才能发出这种请求)

三、进程控制

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

在这里插入图片描述

1. 如何实现进程控制

原语实现进程控制。原语的特点是执行期间不允许中断,只能一气呵成。这种不可被中断的操作即原子操作。原语采用关中断指令和开中断指令实现。

在这里插入图片描述

正常情况下,CPU 每执行完一条指令都会例行检查是否有中断信号需要处理,如果有,则暂停运行当前这段程序,转而执行相应的中断处理程序。CPU 执行了关中断指令后,就不再例行检查中断信号,直到执行开中断指令后才会恢复检查。这样,关中断、开中断之间的这些指令序列就是不可被中断的,这就实现了“原子性”。

显然,开/关中断指令的权限非常大,必然是只允许在核心态下执行的特权指令;

2. 进程相关的原语

进程控制会导致进程状态的转换。无论哪个原语,要做的无非三类事情:

  1. 更新PCB中的信息(如修改进程状态标志、将运行环境保存到PCB、从PCB恢复运行环境)
    1. 所有的进程控制原语一定都会修改进程状态标志;
    2. 剥夺当前运行进程的CPU使用权必然需要保存其运行环境;
    3. 某进程开始运行前必然要恢复期间运行环境;
  2. 将PCB插入合适的队列;
  3. 分配/回收内存;

四、进程通信

顾名思义,进程同行就是指进程之间的信息交换。进程是分配资源的单位(包括内存地址空间),因此各进程拥有的内存地址空间相互独立。为了保证安全,一个进程不能直接访问另一个进程的地址空间。都是进程之间的信息交换又是必须实现的。为了保证进程间的安全通信,操作系统提供了一些方法。

1. 共享存储

共享存储分为两种,一种是基于数据结构的共享,另一种是基于存储区的共享:

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

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

注意:两个进程对共享空间的访问必须是互斥的(互斥访问通过操作系统提供的工具实现);操作系统只负责提供共享空间和同步互斥工具(如P、V操作)。

在这里插入图片描述

2. 管道通信

“管道”是指用于连接读写进程的一个共享文件,又名 pipe 文件。其实就是在内存中开辟一个大小固定的缓冲区。

  • 管道只能采用半双工通信,某一时间段内只能实现单向的传输。如果要实现双向同时通信,则需要设置两个通道。
  • 各进程要互斥地访问管道。
  • 数据以字符流的形式写入管道,当管道写满时,写进程的 write() 系统调用将被阻塞,等待读进程将数据取走。当读进程将数据全部取走后,管道变空,此时读进程的 read() 系统调用被阻塞。
  • 如果没写满,就不允许读。如果没都空,就不允许写。
  • 数据一旦被读出,就从管道中被抛弃,这就意味着读进程最多只能有一个,否则可能会有读错数据的情况。

在这里插入图片描述

3. 消息传递

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

一个格式化消息包括了消息头和消息体,其中消息头包括了发送进程的ID、接收进程的ID、消息类型、消息长度等格式化的信息(计算机网络中发送的“报文”其实就是一种格式化的消息)。

五、线程的概念与特点

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

线程是独立调度的基本单位,一个进程中可以有多个线程,它们共享进程资源。QQ 和浏览器是两个进程,浏览器进程里面有很多线程,例如 HTTP 请求线程、事件响应线程、渲染线程等等,线程的并发执行使得在浏览器中点击一个新链接从而发起 HTTP 请求时,浏览器还可以响应用户的其它事件。

有的进程可能需要“同时”做很多事,而传统的进程只能串行地执行一系列程序。为此,引入了”线程“,来增加并发度;

可以将线程理解为”轻量级进程“。线程是一个基本的CPU执行单位。也是程序执行流的最小单位。引入线程之后,不仅是进程之间可以并发,进程内的个线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务(如QQ视频、文字聊天、传文件);

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

2. 线程的特性和优点

  • 当切换进程时,需要保存/恢复进程运行环境,还需要切换内存地址(更新快表、更新缓存),而同一进程内的各个线程间并发,不需要切换进程运行环境和内存地址空间,省事省力。这里可以看出,引入线程机制后,并发带来的系统开销降低,系统并发性提升。

    注意:从属不同进程的线程间切换,也会导致进程的切换!开销也大!

  • 从属同一进程的各个线程共享进程拥有的资源。各个进程的内存地址相互独立,只能通过请求操作系统内核的帮助来完成进程间通信;而同一进程下的各个线程共享内存地址空间,可以直接通过读/写内存空间进行通信。

  • 引入线程前,进程既是资源分配的基本单位,也是调度的基本单位。引入线程后,进程是资源分配的基本单位,线程是调度的基本单位,线程几乎不拥有资源,只拥有极少量的资源(线程控制块 TCB、寄存器信息、堆栈等)。线程也有运行态、就绪态、阻塞态。在多 CPU 环境下,各个线程也可以分派到不同的 CPU 上并行地执行。

3. 线程的实现方式

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

早期的操作系统(如早期Unix)只支持进程,不支持线程。但是的”线程“是由数据库实现的。

在这里插入图片描述

以同时处理视频、文字聊天、文件传送的 QQ 进程为例,以下是其简单的实现代码:

int main() {
    int i = 0;
    while (true) {
        if(i == 0){处理视频聊天的代码;}
        if(i == 1){处理文字聊天的代码;}
        if(i == 2){处理文件传输的代码;}
        i = (i + 1) % 3; // i 的值为 0,1,2,0,1,2 ...
    }
}

从代码的角度看,线程其实就是一段代码逻辑。上述三段代码逻辑上可以看作三个“线程”。while 循环就是一个最弱智的“线程库”,线程库完成了对线程的管理工作(如调度)。

用户级线程由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责(包括线程切换);线程切换可以在用户态下完成,无需操作系统干预,这种线程的实现方式在用户看来是有多个线程。但是在操作系统内核看来,意识不到线程的存在。“用户级线程”就是“从用户视角看能看到的线程。”

优缺点

优点:用户及线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高

缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行。

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

内核级线程是指由操作系统支持的线程,内核级线程的管理工作由操作系统内核完成。线程调度、切换等工作都由内核负责,因此内核级线程的切换必然需要在核心态下才能完成。

在这里插入图片描述

操作系统会为每个内核级线程建立相应的 TCB(Thread Control Block,线程控制块),通过 TCB 对线程进行管理。“内核级线程”就是“从操作系统内核视角能看到的线程”

优缺点

优点:当一个线程被阻塞后,别的线程还可以继续进行,并发能力强。多线程可在多核处理机上并行运行。

缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大。

4. 线程模式

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

4.1 一对一模型

一对一模型即一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程。即上述所提到的内核级线程。

4.2 多对一模型

多对一模型:多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程 。即上述提到的用户级线程。

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

4.3 多对多模型

多对多模型:n 用户级线程映射到 m 个内核级线程(n >= m)。每个用户进程对应 m 个内核级线程。

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

可以这么理解:用户级线程是“代码逻辑”的载体;内核级线程是“运行机会”的载体。内核级线程才是处理机分配的单位。

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值