站在设计者的角度看进程与线程

站在设计者的角度看进程与线程

进程是操作系统中最核心的概念,是对正在运行的程序的一个抽象。要运行一个程序,需要有程序的代码和程序使用的必须数据,而这两者在CPU中经过动态计算等一系列活动以及活动所需的内存空间、寄存器和文件句柄的资源就共同构成了进程抽象。

寄存器等硬件必备知识可以参考我的另一篇文章:《计算机硬件组成》

进程

现在大部分的计算机都拥有多核,因此可以同时运行多个进程,即使是单核,也可以通过就像视频帧的连续快速播放一样快速的在多个进程之间进行切换,实现一种并行的错觉,这其实就是并发(伪并行)。

事实证明,并行和并发在许多场景下都有大量的应用,因此操作系统在实现进程抽象时不仅需要考虑内存中只有一道单进程执行的简单场景,而应该设计一种支持并行和并发的进程抽象。你可能认为这很简单,但事实上,经过许多才华卓越的学者和设计师多年的努力(从无到有和从有到优的难度是有差别的),才最终形成当前广泛使用的用于描述并行的一种概念模型--顺序进程,这使得并行更容易理解和处理。

顺序进程

操作系统是计算机系统的核心部分,负责管理硬件资源和提供公共服务以运行各种应用程序。在多任务和多用户环境中,操作系统需要有效地管理和调度多个任务同时运行,这些任务可以是并行的或者是分时的。为了更有效地设计和实现这种复杂的任务管理,操作系统的设计者们采用了“顺序进程”的概念模型来描述并处理并行活动。

1. 什么是顺序进程?

顺序进程(简称进程),或称为“线性进程”,是操作系统中的一个抽象概念,用来将复杂的并行和并发操作简化为看似顺序的任务单元。每个顺序进程都可以视为一个独立的、按顺序执行的任务流,操作系统负责调度这些任务流,使其在多个CPU核心或者在单个CPU的不同时间片上执行。

在计算机的CPU中,有一系列的寄存器,其中有一个程序计数器,它保存了程序的下一条指令的地址,CPU根据这个地址从内存或磁盘中取出对应的指令执行之。这样依次取指、译指和执行指令等的活动可以算是CPU的核心功能了,而这也是程序执行的关键环节,其具体的过程如下:

在计算机架构中,CPU执行指令的过程包括几个关键步骤,通常被称为指令周期。指令周期可以细分为取指(Fetch)、译指(Decode)、执行(Execute)、访存(Memory Access)、写回(Write Back)等阶段。这一系列操作确保了计算机能够正确、高效地执行程序代码。下面详细解释这些步骤:

1. 取指 (Fetch)

取指阶段是指令执行周期的第一步,主要任务是从内存中读取指令。CPU利用程序计数器(PC)来存储下一条要执行的指令的地址。程序计数器的值指向内存中的一个位置,CPU从这个位置把指令加载到指令寄存器中。完成这一步后,程序计数器的值会更新,指向下一条指令的地址。

2. 译指 (Decode)

在译指阶段,CPU对取出的指令进行解码。这一步骤需要分析指令寄存器中的指令,确定指令的类型(如算术运算、数据传输、控制指令等)。解码过程通常涉及以下几个方面:

操作码识别:确定指令的操作类型,比如加法、减法、数据加载等。寄存器识别:识别出指令中涉及的寄存器。立即数提取:如果指令中包含立即数(直接提供的数值),则提取这些数值。

3. 执行 (Execute)

执行阶段是将解码阶段得到的信息转化为实际操作的过程。根据指令的类型,这可能涉及以下操作:

算术逻辑单元(ALU)运算:执行所有的算术和逻辑运算。地址计算:如果指令涉及数据访问,计算数据的确切内存地址。条件分支判断:对于跳转指令,判断是否符合跳转条件,并更新程序计数器的值。

4. 访存 (Memory Access)

访存阶段用于访问内存中的数据,这一步只有在需要的时候才执行。例如,一个加载(Load)指令会在这一阶段从计算出的地址读取数据,而存储(Store)指令会将数据写入指定地址。不是所有的指令都需要访存阶段。

5. 写回 (Write Back)

最后阶段是写回阶段,此时执行结果将被写回到目标寄存器或内存中。这标志着一条指令的执行周期的完成。

图解示例

为了更直观地理解,可以想象以下的流程图:

[程序计数器] -> [取指] -> [指令寄存器] -> [译指]

| ↓

| [执行]

| ↓

└----------------------------------> [访存]

[写回]

在指令执行过程中,从程序计数器(PC)直接到访存阶段的箭头可能初看起来有些令人困惑,但这实际上反映了一些特定类型的指令执行逻辑,尤其是涉及控制转移(如跳转)和部分特殊操作的情况。

这一连串的步骤(取指、译指、执行、访存、写回)使得CPU能够有效地执行存储在内存中的指令。每个阶段都是指令执行不可缺少的一部分,确保了指令能够被正确处理和执行。这些步骤共同组成了CPU的指令执行周期,是计算机运行任何程序的基础。

接着说重点,在顺序进程中的一个关键点是:对唯一的物理程序计数器进行了抽象,每个进程都拥有一个属于自己的逻辑程序计数器,这使得该模型具有了并行和并发的能力,因为在进行进程切换时仅需保存其程序计数器和其他必要信息,并调入下一个进程的相关信息,那么就能实现进程的快速切换,而CPU只要继续按照其程序计数器执行就可以了,这比跟踪CPU如何在多个进程间来回切换要简单太多。

从外部看,每个顺序进程表现为顺序执行,操作系统通过精细的调度算法(如轮转调度、优先级调度等)来管理这些进程的执行。顺序进程的优势也就得到了体现:

简化设计和实现:通过顺序进程,系统设计者可以将复杂的并发性问题分解为较简单的、独立的顺序任务单元,每个单元内部不涉及并发处理,从而简化了并发程序的设计和调试过程。提高可理解性:顺序进程模型使程序的流程更加直观易懂,程序员可以像编写顺序代码一样思考并发问题,而不必直接面对复杂的同步和竞争状态问题。方便资源管理:操作系统可以更方便地进行资源分配和管理,如CPU时间、内存等,因为每个进程都是独立的,资源的分配可以明确且具有预测性。优化性能和响应时间:顺序进程模型允许操作系统优化进程间的切换,减少上下文切换的开销,提高系统的整体性能和响应速度。

顺序进程的概念极大地方便了并行程序的开发和运行,使得设计者能够更加集中于程序逻辑的实现,而不是低层次的资源管理和同步控制。这种模型是现代操作系统能够有效支持多任务处理和资源共享的基础。通过这种方式,操作系统为复杂的并行计算提供了一种更简洁、更高效的管理策略,操作系统作为程序的三大浪漫之一,我想从这一点上可见一斑,惊喜的是,其浪漫和魅力远不止于此。

本文后续将继续深入探讨关于进程和线程的更多内容,包括:进程的生命周期和实现,有了支持多进程的顺序进程模型为什么还需要线程的概念,经典的线程模型及其各种实现方式的原理和优劣,对于应用程序开发者和操作系统都必不可少的进程与线程通信方式等等问题,你最关注哪一点呢?由于笔者时间关系,本文后续将继续更新,喜欢的同学可以关注我,您的支持就是我创作的强大动力!

关键点

进程是操作系统中最核心的概念,是对正在运行的程序的一个抽象。要运行一个程序,需要有程序的代码和程序使用的必须数据,而这两者在CPU

相关文章