进程的开销比线程大在了哪里?

news2025/1/16 3:36:18
  • 进程内部都有哪些数据?

  • 为什么创建进程的成本很高?

这样的问题确实不好回答,除非你真正理解了进程和线程的原理,否则很容易掉入面试大坑。探究问题背后的原理,围绕面试题展开理论与实践知识的学习。真正理解进程和线程原理,从容应对面试。

进程和线程

进程(Process),顾名思义就是正在执行的应用程序,是软件的执行副本。而线程是轻量级的进程。

进程是分配资源的基础单位。而线程很长一段时间被称作轻量级进程(Light Weighted Process),是程序执行的基本单位。

在计算机刚刚诞生的年代,程序员拿着一个写好程序的闪存卡,插到机器里,然后电能推动芯片计算,芯片每次从闪存卡中读出一条指令,执行后接着读取下一条指令。闪存中的所有指令执行结束后,计算机就关机。

Drawing 0.png

早期的 ENIAC

一开始,这种单任务的模型,在那个时代叫作作业(Job),当时计算机的设计就是希望可以多处理作业。图形界面出现后,人们开始利用计算机进行办公、购物、聊天、打游戏等,因此一台机器正在执行的程序会被随时切来切去。于是人们想到,设计进程和线程来解决这个问题。

每一种应用,比如游戏,执行后是一个进程。但是游戏内部需要图形渲染、需要网络、需要响应用户操作,这些行为不可以互相阻塞,必须同时进行,这样就设计成线程。

资源分配问题

设计进程和线程,操作系统需要思考分配资源。最重要的 3 种资源是:计算资源(CPU)、内存资源和文件资源。早期的 OS 设计中没有线程,3 种资源都分配给进程,多个进程通过分时技术交替执行,进程之间通过管道技术等进行通信。

但是这样做的话,设计者们发现用户(程序员),一个应用往往需要开多个进程,因为应用总是有很多必须要并行做的事情。并行并不是说绝对的同时,而是说需要让这些事情看上去是同时进行的——比如图形渲染和响应用户输入。于是设计者们想到了,进程下面,需要一种程序的执行单位,仅仅被分配 CPU 资源,这就是线程。

轻量级进程

线程设计出来后,因为只被分配了计算资源(CPU),因此被称为轻量级进程。被分配的方式,就是由操作系统调度线程。操作系统创建一个进程后,进程的入口程序被分配到了一个主线程执行,这样看上去操作系统是在调度进程,其实是调度进程中的线程。

这种被操作系统直接调度的线程,我们也成为内核级线程。另外,有的程序语言或者应用,用户(程序员)自己还实现了线程。相当于操作系统调度主线程,主线程的程序用算法实现子线程,这种情况我们称为用户级线程。Linux 的 PThread API 就是用户级线程,KThread API 则是内核级线程。

分时和调度

因为通常机器中 CPU 核心数量少(从几个到几十个)、进程&线程数量很多(从几十到几百甚至更多),你可以类比为发动机少,而机器多,因此进程们在操作系统中只能排着队一个个执行。每个进程在执行时都会获得操作系统分配的一个时间片段,如果超出这个时间,就会轮到下一个进程(线程)执行。再强调一下,现代操作系统都是直接调度线程,不会调度进程。

分配时间片段

如下图所示,进程 1 需要 2 个时间片段,进程 2 只有 1 个时间片段,进程 3 需要 3 个时间片段。因此当进程 1 执行到一半时,会先挂起,然后进程 2 开始执行;进程 2 一次可以执行完,然后进程 3 开始执行,不过进程 3 一次执行不完,在执行了 1 个时间片段后,进程 1 开始执行;就这样如此周而复始。这个就是分时技术。

Lark20201104-145535.png

下面这张图更加直观一些,进程 P1 先执行一个时间片段,然后进程 P2 开始执行一个时间片段, 然后进程 P3,然后进程 P4……

在这里插入图片描述

注意,上面的两张图是以进程为单位演示,如果换成线程,操作系统依旧是这么处理。

进程和线程的状态

一个进程(线程)运行的过程,会经历以下 3 个状态:

  • 进程(线程)创建后,就开始排队,此时它会处在“就绪”(Ready)状态;

  • 当轮到该进程(线程)执行时,会变成“运行”(Running)状态;

  • 当一个进程(线程)将操作系统分配的时间片段用完后,会回到“就绪”(Ready)状态。

我这里一直用进程(线程)是因为旧的操作系统调度进程,没有线程;现代操作系统调度线程。

在这里插入图片描述
有时候一个进程(线程)会等待磁盘读取数据,或者等待打印机响应,此时进程自己会进入“阻塞”(Block)状态。

在这里插入图片描述

因为这时计算机的响应不能马上给出来,而是需要等待磁盘、打印机处理完成后,通过中断通知 CPU,然后 CPU 再执行一小段中断控制程序,将控制权转给操作系统,操作系统再将原来阻塞的进程(线程)置为“就绪”(Ready)状态重新排队。

而且,一旦一个进程(线程)进入阻塞状态,这个进程(线程)此时就没有事情做了,但又不能让它重新排队(因为需要等待中断),所以进程(线程)中需要增加一个“阻塞”(Block)状态。

在这里插入图片描述

进程和线程的设计

接下来我们思考几个核心的设计约束:

  1. 进程和线程在内存中如何表示?需要哪些字段?

  2. 进程代表的是一个个应用,需要彼此隔离,这个隔离方案如何设计?

  3. 操作系统调度线程,线程间不断切换,这种情况如何实现?

  4. 需要支持多 CPU 核心的环境,针对这种情况如何设计?

接下来我们来讨论下这4个问题。

进程和线程的表示

可以这样设计,在内存中设计两张表,一张是进程表、一张是线程表。

进程表记录进程在内存中的存放位置、PID 是多少、当前是什么状态、内存分配了多大、属于哪个用户等,这就有了进程表。如果没有这张表,进程就会丢失,操作系统不知道自己有哪些进程。这张表可以考虑直接放到内核中。

在这里插入图片描述

细分的话,进程表需要这几类信息。

  • 描述信息:这部分是描述进程的唯一识别号,也就是 PID,包括进程的名称、所属的用户等。

  • 资源信息:这部分用于记录进程拥有的资源,比如进程和虚拟内存如何映射、拥有哪些文件、在使用哪些 I/O 设备等,当然 I/O 设备也是文件。

  • 内存布局:操作系统也约定了进程如何使用内存。如下图所示,描述了一个进程大致内存分成几个区域,以及每个区域用来做什么。 每个区域我们叫作一个段。

在这里插入图片描述

操作系统还需要一张表来管理线程,这就是线程表。线程也需要 ID, 可以叫作 ThreadID。然后线程需要记录自己的执行状态(阻塞、运行、就绪)、优先级、程序计数器以及所有寄存器的值等等。线程需要记录程序计数器和寄存器的值,是因为多个线程需要共用一个 CPU,线程经常会来回切换,因此需要在内存中保存寄存器和 PC 指针的值。

用户级线程和内核级线程存在映射关系,因此可以考虑在内核中维护一张内核级线程的表,包括上面说的字段。

如果考虑到这种映射关系,比如 n-m 的多对多映射,可以将线程信息还是存在进程中,每次执行的时候才使用内核级线程。相当于内核中有个线程池,等待用户空间去使用。每次用户级线程把程序计数器等传递过去,执行结束后,内核线程不销毁,等待下一个任务。这里其实有很多灵活的实现,总体来说,创建进程开销大、成本高;创建线程开销小,成本低

隔离方案

操作系统中运行了大量进程,为了不让它们互相干扰,可以考虑为它们分配彼此完全隔离的内存区域,即便进程内部程序读取了相同地址,而实际的物理地址也不会相同。这就好比 A 小区的 10 号楼 808 和 B 小区的 10 号楼 808 不是一套房子,这种方法叫作地址空间,我们将在“21 讲”的页表部分讨论“地址空间”的详细内容。

所以在正常情况下进程 A 无法访问进程 B 的内存,除非进程 A 找到了某个操作系统的漏洞,恶意操作了进程 B 的内存,或者利用进程间通信的手段。

在这里插入图片描述

对于一个进程的多个线程来说,可以考虑共享进程分配到的内存资源,这样线程就只需要被分配执行资源。

进程(线程)切换

进程(线程)在操作系统中是不断切换的,现代操作系统中只有线程的切换。 每次切换需要先保存当前寄存器的值的内存,注意 PC 指针也是一种寄存器。当恢复执行的时候,就需要从内存中读出所有的寄存器,恢复之前的状态,然后执行。

在这里插入图片描述

上面讲到的内容,我们可以概括为以下 5 个步骤:

  1. 当操作系统发现一个进程(线程)需要被切换的时候,直接控制 PC 指针跳转是非常危险的事情,所以操作系统需要发送一个“中断”信号给 CPU,停下正在执行的进程(线程)。

  2. 当 CPU 收到中断信号后,正在执行的进程(线程)会立即停止。注意,因为进程(线程)马上被停止,它还来不及保存自己的状态,所以后续操作系统必须完成这件事情。

  3. 操作系统接管中断后,趁寄存器数据还没有被破坏,必须马上执行一小段非常底层的程序(通常是汇编编写),帮助寄存器保存之前进程(线程)的状态。

  4. 操作系统保存好进程状态后,执行调度程序,决定下一个要被执行的进程(线程)。

  5. 最后,操作系统执行下一个进程(线程)。

在这里插入图片描述

当然,一个进程(线程)被选择执行后,它会继续完成之前被中断时的任务,这需要操作系统来执行一小段底层的程序帮助进程(线程)恢复状态。

在这里插入图片描述

一种可能的算法就是通过栈这种数据结构。进程(线程)中断后,操作系统负责压栈关键数据(比如寄存器)。恢复执行时,操作系统负责出栈和恢复寄存器的值。

多核处理

在多核系统中我们上面所讲的设计原则依然成立,只不过动力变多了,可以并行执行的进程(线程)。通常情况下,CPU 有几个核,就可以并行执行几个进程(线程)。这里强调一个概念,我们通常说的并发,英文是 concurrent,指的在一段时间内几个任务看上去在同时执行(不要求多核);而并行,英文是 parallel,任务必须绝对的同时执行(要求多核)。

在这里插入图片描述

比如一个 4 核的 CPU 就好像拥有 4 条流水线,可以并行执行 4 个任务。一个进程的多个线程执行过程则会产生竞争条件,这块我们会在“19 讲”锁和信号量部分给你介绍。因为操作系统提供了保存、恢复进程状态的能力,使得进程(线程)也可以在多个核心之间切换。

创建进程(线程)的 API

用户想要创建一个进程,最直接的方法就是从命令行执行一个程序,或者双击打开一个应用。但对于程序员而言,显然需要更好的设计。

站在设计者的角度,你可以这样思考:首先,应该有 API 打开应用,比如可以通过函数打开某个应用;另一方面,如果程序员希望执行完一段代价昂贵的初始化过程后,将当前程序的状态复制好几份,变成一个个单独执行的进程,那么操作系统提供了 fork 指令。

在这里插入图片描述

也就是说,每次 fork 会多创造一个克隆的进程,这个克隆的进程,所有状态都和原来的进程一样,但是会有自己的地址空间。如果要创造 2 个克隆进程,就要 fork 两次。

你可能会问:那如果我就是想启动一个新的程序呢?

我在上文说过:操作系统提供了启动新程序的 API。

你可能还会问:如果我就是想用一个新进程执行一小段程序,比如说每次服务端收到客户端的请求时,我都想用一个进程去处理这个请求。

如果是这种情况,我建议你不要单独启动进程,而是使用线程。因为进程的创建成本实在太高了,因此不建议用来做这样的事情:要创建条目、要分配内存,特别是还要在内存中形成一个个段,分成不同的区域。所以通常,我们更倾向于多创建线程。

不同程序语言会自己提供创建线程的 API,比如 Java 有 Thread 类;go 有 go-routine(注意不是协程,是线程)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/415729.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7虚拟机下hbase的使用案例讲解

系列文章目录 centos7虚拟机在集群zookeeper上面配置hbase的具体操作步骤 centos7虚拟机配置集群时间同步的操作步骤_centos虚拟机时间同步 centos7配置zookeeper本地模式与集群模式的详细教程 卸载centos7自带的jdk的操作步骤_centos7 卸载java 虚拟机centos7配置Hadoop单…

如何用 Vitis HLS 实现 OpenCV 仿真

这篇文章的基础是《Windows上快速部署Vitis HLS OpenCV仿真库》,我们使用的版本是Vitis HLS 2022.2,其他版本BUG不清楚,目前已知2021版本有BUG,只能使用其他方式,本文不适合。 这次选择中值滤波这个常规算法作为演示算…

Springboot电脑商城项目

目录 系统概述与环境搭建 1 系统开发及运行环境 2 项目分析 3 创建数据库 4 创建Spring Initializr项目 5 配置并运行项目 6 导入前端项目 用户注册 1 用户-创建数据表 2 用户-创建实体类 3 用户-注册-持久层 4 用户-注册-业务层 5 用户-注册-控制器 6 用户-注册…

归并排序(递归实现)

上一次我们说了快排的其他版本,还有就是快排的非递归实现 这次我们就说一哈归并排序,归并排序也是很厉害的一种排序,而且归并排序的时间复杂度可以说成标准的O(n log n) 下面我们就来看一下归并排序 我们先来看一下什么是归并排序 假设我…

Scratch蓝桥杯实战训练 —— 巧解“韩信点兵”难题的五种方式

“韩信点兵”蓝桥杯问题描述: “蓝桥杯”中有一道有趣的 Scratch 编程题,题目要求为:韩信点兵 扩展知识: 这道题叫“中国余数定理”,又叫“孙子定理”,也叫“韩信点兵问题”,是我国古代数学智慧…

Faster-RCNN代码解读3:制作自己的数据加载器

Faster-RCNN代码解读3:制作自己的数据加载器 前言 ​ 因为最近打算尝试一下Faster-RCNN的复现,不要多想,我还没有厉害到可以一个人复现所有代码。所以,是参考别人的代码,进行自己的解读。 ​ 代码来自于B站的UP主&…

Node【三】Buffer 与 Stream

文章目录🌟前言🌟Buffer🌟 Buffer结构🌟 什么时候用Buffer🌟 Buffer的转换🌟 Buffer使用🌟 创建Buffer🌟 字符串转Buffer🌟 Buffer转字符串🌟 拼接Buffer&…

python 理解BN、LN、IN、GN归一化、分析torch.nn.LayerNorm()和torch.var()工作原理

目录 前言: 简言之BN、LN、IN、GN等归一化的区别: 批量归一化(Batch Normalization,BN) 优点 缺点 计算过程 层归一化(Layer Normalization,LN) 优点 计算过程 总结 分析torch.nn.LayerNorm()工作原理 分析torch.var(…

Vue2-黑马(十一)

目录: (1)vue2-联调准备 (2)vue2-登录实战-国际化 (3)vue2实战-登录-login-index.vue (1)vue2-联调准备 登录这个请求,并不是发给后台的,现在还…

浙大MBA提面申请材料的三六九等……

每年浙大MBA项目提前批面试申请的每个批次中都会有部分材料因为某些原因而被淘汰,无缘面试资格。考生们由最初的不理解到逐渐隐约的理解,行至今日也可以大体接受材料被刷这个结果,当然其中含有一部分面上资质背景还可以的考生,等到…

Faster-RCNN代码解读2:快速上手使用

Faster-RCNN代码解读2:快速上手使用 前言 ​ 因为最近打算尝试一下Faster-RCNN的复现,不要多想,我还没有厉害到可以一个人复现所有代码。所以,是参考别人的代码,进行自己的解读。 ​ 代码来自于B站的UP主(…

中国电子学会2023年03月份青少年软件编程Scratch图形化等级考试试卷四级真题(含答案)

2023-03 Scratch四级真题 分数:100 题数:24 测试时长:90min 一、单选题(共10题,共30分) 1.编写一段程序,从26个英文字母中,随机选出10个加入列表a。空白处应填入的代码是?(C&am…

Flink (十二) --------- Flink CEP

目录一、基本概念1. CEP 是什么2. 模式 (Pattern)3. 应用场景二、快速上手1. 需要引入的依赖2. 一个简单实例三、模式 API(Pattern API)1. 个体模式2. 组合模式3. 模式组4. 匹配后跳过策略四、模式的检测处理1. 将模式应用到流上2. 处理匹配事件3. 处理超…

【高项】项目整体管理、范围管理与进度管理(十大管理)

【高项】项目整体管理与范围管理 文章目录1、项目整体管理1.1 整体管理的过程1.2 制定项目章程(启动)1.3 制订项目管理计划(规划)1.4 指导与管理项目执行(执行)1.5 监控项目工作与实施整体变更控制&#xf…

Systemverilog中operators和expression的记录

1. Equality operators Equality operators有三种: Logical equality:, !,该运算符中如果运算数包含有x/z态,那么结果就是x态。只有在两边的bit都不包含x/z态,最终结果才会为0(False)或1(True)Case equality&#xf…

中云盾DDoS云防护系统

中云盾 DDoS 防护系统作为公司级网络安全产品,为各类业务提供专业可靠的 DDoS/CC 攻击防护。在黑客攻防对抗日益激烈的环境下, DDoS 对抗不仅需要 “降本” 还需要 “增效”。 为什么上云? 云原生作为近年来相当热门的概念,无论…

RHCE-NTP、SSH服务器

1.配置ntp时间服务器,确保客户端主机能和服务主机同步时间​ 服务器端: (1)首先安装chrony软件: dnf install -y chrony (2)配置时间同步源: 进入vim /etc/chrony.conf &#xf…

引用和指针

总结 引用: 因为引用是变量的别名,所以引用必须初始化 因为引用不存在自己的地址,所以指针不能指向引用,即不能定义引用的指针 因为引用不是对象,但是引用又要绑定一个对象,所以不能定义引用的引用 in…

一篇文章看懂C++三大特性——多态的定义和使用

目录 前文 一,什么是多态? 1.1 多态的概念 二, 多态的定义及实现 2.1 多态的构成条件 2.2 虚函数 2.3 虚函数的重写 2.3.1 虚函数重写的两个例外 2.4 C override 和 final 2.5 重载,重写(覆盖),隐藏(重定义)的区别 三,抽…

代码随想录刷题-双指针总结篇

文章目录双指针移除元素习题我的解法双指针优化反转字符串习题我的解法剑指 Offer 05. 替换空格习题我的解法正确解法反转字符串里的单词习题我的解法反转链表习题我的解法删除链表的倒数第 N 个节点习题我的解法相交链表习题我的解法环形链表 II习题我的解法三数之和习题我的解…