目录

一、前言回顾

计算机是如何工作

操作系统

进程(任务)

进程管理

PCB 核心属性

二、本课内容

进程调度

4. 进程状态

5. 进程的优先级

6. 进程的上下文

7. 进程的记账信息

PCB 属性汇总

进程隔离性

进程间通信


一、前言回顾

计算机是如何工作

CPU 的工作过程~

3 + 14为例,对应的指令序列为:

  • LOAD A

  • LOAD B

  • ADD

  • SAVE A

CPU 执行指令分为三步:

  1. 取指令

  2. 解析指令

  3. 执行指令

操作系统

操作系统的核心作用:

  1. 对下,管理各种硬件设备

  2. 对上,给各种软件提供稳定的运行环境~

进程(任务)

  • 运行起来的程序~

  • 二进制的可执行文件(硬盘)→ 运行后得到进程(内存)

  • 进程是操作系统资源分配的基本单位。

进程管理

进程管理的两个核心动作:

  1. 描述:使用 PCB 结构体,把进程的各种属性表示出来。

  2. 组织:通过双向链表,把多个 PCB 串起来~~

PCB 核心属性

PCB(进程控制块)的核心属性包括:

  1. PID

  2. 内存指针

  3. 文件描述符表

二、本课内容

进程调度

假设 CPU 核心有 20 个,但进程数上百个。如何利用有限的 CPU 核心,让这么多进程“同时执行”

CPU 通过并行并发两种方式实现:

  • 并行:两个 CPU 核心,分别执行不同进程的指令。

  • 并发:一个 CPU 核心,通过“分时复用”方式,实现“同时执行”(CPU 单核心时代,多任务操作系统全靠并发)。

→ 程序员感知不到 N 个进程之间是并行还是并发,都是操作系统自身负责调度的。咱们写代码,不关心并行还是并发,后续把并行和并发统称为 并发

4. 进程状态

进程有很多种状态,简单理解分成两种:

  1. 就绪:默认情况下,ABC 三个同事都处于“就绪”状态(“随时可安排工作”)。

  2. 阻塞:比如有一天,A 要出差~~ 出差的时间里,就无法给 A 安排工作了吧~~ 此时“阻塞”。阻塞意味着该进程无法参与到 CPU 的调度执行上~~

以前也接触过阻塞~

scanner.nextInt()这样的代码会使你的进程阻塞~~

System.out.println("请输入要插入的 id:");
int id = scanner.nextInt();

这里是需要等待用户输入的~~

5. 进程的优先级

ABC 我排工作日程的时候,不是完全公平的~~

  • 周一周二周三:安排 A 的工作 (A 负责核心模块开发,优先级高)

  • 周四周五周六:安排 B 的工作 (B 负责测试联调,也是重要任务)

  • 至于 C,看整体进度了~~ 假设如果 B 的工作遇到阻塞,把 B 的时间匀出来一天,给 C 安排工作~~

进程的优先级,决定了哪个进程要优先安排 CPU 资源~~

你的电脑上,同时运行着开发环境和即时通讯软件

同事发来紧急消息,需要立即响应 → 实时操作~~ 有更多的 CPU 资源~~

有些特殊设备,优先级更关键~~ 汽车的智能驾驶系统~~ 负责刹车任务,优先级一定得是最高的~~

6. 进程的上下文

一个进程调度到 CPU 上执行了,离开 CPU,过一段时间,还会回到 CPU 上~~

  • 离开时:保存信息(类似于项目的存档功能~~)

  • 回来时:继续之前的位置往下执行(读档)

在给 ABC 三位同事安排工作的过程中,需要准备“工作日志”详细记录每次工作后的进度~~ 把关键事务记录下来~~

  • 我在安排 A 的工作时,A 说:下周一要提交模块一的设计文档,你记得跟进一下~~ 我说好的,于是就需要记录到工作日志上~~

  • 我在安排 B 的工作时,B 说:下周三要和客户联调,需要提前准备测试数据,你也跟进一下~~ 我也说好的,也需要记录到工作日志上~~

→ 这就是上下文~~

CPU 内部有很多寄存器~~ 用于保存当前程序运行的一些中间状态~~

除了保存数据的寄存器之外,还有一些特殊的寄存器:

  • 记录当前指令执行到哪一条了~~

  • 记录当前程序的函数调用关系

进程在 CPU 上执行的时候~~ 寄存器的值不停发生变换~~

进程要离开 CPU 的时候,把这一时刻,CPU 上这些寄存器的值,全都拷贝出来,保存到内存里(PCB 的结构体)保存上下文(存档)

进程后续回到 CPU,也是把之前 PCB 保存的这些寄存器的值,重写入到 CPU 的寄存器中~~恢复上下文(读档)

上述功能操作系统内部实现好了~~

7. 进程的记账信息

统计机制,统计每个进程,都在 CPU 上运行了多久~~

优先级机制下,就可能使某个进程吃到的 cpu 资源非常少。通过记账信息,识别出这一点,从而灵活调整,给这个进程多分点资源~~

PCB 属性汇总

PCB 中属性非常非常多~~ 包括:

  1. PID

  2. 内存指针

  3. 文件描述符表

  4. 状态

  5. 优先级

  6. 上下文

  7. 记账信息

→ 这些属性支撑进程调度~~

进程隔离性

  • 每个进程有自己独立的内存空间(进程的隔离性)

  • 事务隔离性:多个事务同时执行,不要相互影响

  • 进程隔离性:多个进程执行的时候,也不要相互影响~~

之前学 C 的时候,指针~~

int* p = &a;
*p = 100;

p = 0xaabbccdd → 能否通过这样的 *p 操作,修改别的进程的内存数据呢?

不能~~

操作系统要给应用程序提供稳定的运行环境~~ 操作系统给每个进程划分了独立的内存地址空间~~ 每个进程只能访问自己的内存数据~~ 无法访问别的进程的内容~~

进程间通信

如果确实有时候需要多个进程协同工作~~ ⇒ 进程间通信了~~

常见的进程间通信方式:

  1. 管道

  2. 共享内存

  3. 文件

  4. 网络

  5. 信号量

  6. 信号

在 Java 生态中,不鼓励使用多进程编程。

这些机制很多在 JVM 中并没有封装~~

确实想进行多进程编程,Java 的生态中最推荐的方式是:网络

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐