【QandA C++】进程、线程、协程、进程间通信的方式、线程同步机制、守护线程、僵尸进程、孤儿进程、线程切换的资源等重点知识汇总

目录

进程、线程和协程的区别

线程和进程的区别

进程

线程

进程间通信方式

线程同步机制

守护进程、僵尸进程、孤儿进程

进程/线程切换过程切换的资源有哪些


进程、线程和协程的区别

进程

线程

协程

定义

资源分配和拥有的基本单位

程序执行的基本单位

用户态的轻量级线程,线程内部调度的基本单位

切换情况

进程CPU环境(栈、寄存器、页表和文件句柄等)的保存以及新调度的进程CPU环境的设置

保存和设置程序计数器、少量寄存器和栈的内容

先将寄存器上下文和栈保存,等切换回来的时候再进行恢复

切换者

操作系统

操作系统

用户

切换过程

用户态->内核态->用户态

用户态->内核态->用户态

用户态(没有陷入内核)

调用栈

内核栈

内核栈

用户栈

拥有资源

CPU资源、内存资源、文件资源和句柄等

程序计数器、寄存器、栈和状态字

拥有自己的寄存器上下文和栈

并发性

不同进程之间切换实现并发,各自占有CPU实现并行

一个进程内部的多个线程并发执行

同一时间只能执行一个协程,而其他协程处于休眠状态,适合对任务进行分时处理

系统开销

切换虚拟地址空间,切换内核栈和硬件上下文,CPU高速缓存失效、页表切换,开销很大

切换时只需保存和设置少量寄存器内容,因此开销很小

直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快

通信方面

进程间通信需要借助操作系统

线程间可以直接读写进程数据段(如全局变量)来进行通信

共享内存、消息队列

线程和进程的区别

  1. 执行单元:进程是操作系统资源分配的基本单位,是一个完整的运行环境,
  2. 而线程则是任务调度和执行的基本单位
  3. 资源分配和管理:
  4. 每个进程都有自己的独立的进程地址空间、系统资源和文件描述符表,
  5. 而线程共享进程的资源。但每个线程各自都有一套独立的寄存器和栈
  6. 因此,进程之间的切换需要一定的时间和开销,而线程之间的切换则相对快速和轻量级。
  7. 由于同一进程的各线程间共享内存和文件资源,那么在线程之间数据传递的时候,就不需要经过内核了,这就使得线程之间的数据交互效率更高了;
  8. 通信方式:
  9. 进程间通信需要特定的机制,如管道、消息队列、共享内存、信号量等。
  10. 同个进程下的线程之间都是共享进程的资源,只要是共享变量都可以做到线程间通信,比如全局变量,所以对于线程间关注的不是通信方式,而是关注多线程竞争共享资源的问题,信号量也同样可以在线程间实现互斥与同步:
  11. 安全性:
  12. 由于进程之间是相互隔离的,因此一个进程中的代码不会对其他进程产生影响
  13. 线程之间则可能会相互干扰或者造成数据不一致等问题一个线程的错误可能会导致整个进程崩溃。
  14. 从内核的角度来说,Linux把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是内存管理机制来处理线程,而是和进程一样,使用相同的调度算法和内存管理机制。

进程

进程是操作系统中的一个独立的执行单元,它包含了程序的代码、数据以及一些运行时的状态信息。每个进程都有自己的内存空间,独立于其他进程,使其能够互相隔离。

进程可以通过多种方式创建,包括通过shell命令启动程序、由其他进程派生(fork)新进程。新进程拥有自己的进程标识符(PID)。

操作系统对进程的管理方法是先描述再组织。创建一个进程实际上就是先将进程的代码和数据加载到内存上,接着操作系统对该进程进行描述形成对应的PCB(PCB是对进程控制块的统称),Linux下描述进程控制块的结构体叫做task_struct。在Linux的根目录下有proc文件,这个文件里面就包含大量的进程信息,可以使用ps命令来查看进程信息

进程在其生命周期中可以处于不同的状态,包括就绪态、运行态、等待态等。就绪态表示进程已准备好执行但尚未获得CPU时间片,运行态表示进程正在执行,等待态表示进程正在等待某个事件的发生。

操作系统负责调度进程以便它们可以共享CPU时间。进程调度算法决定了哪个进程获得CPU时间,通常使用抢占式调度算法。

进程可以通过多种方式进行通信,包括管道、套接字、消息队列、共享内存等。这些机制允许进程在不同的地址空间中传递数据和信息。

进程可以正常退出,也可以被强制终止。当进程完成其工作或者遇到错误时,它会释放其资源并终止。操作系统也可以通过发送信号来终止进程。

系统管理员可以使用工具来监控和管理系统中的进程,例如ps、top、kill等命令。这些工具允许管理员查看进程的状态、资源使用情况以及终止不需要的进程。

线程

线程是进程内的一个独立执行单元,它与同一进程中的其他线程共享相同的进程内存空间。线程包含了程序代码、数据以及一些运行时状态信息,因此线程比进程更轻量级,创建和切换开销较小,可以更有效地利用系统资源。但它们与进程内的其他线程共享相同的资源,如文件描述符和全局变量。

Linux下的线程是最小的执行单位,调度的基本单位。从内核的角度来说,Linux把所有的线程都当做进程来实现。内核并没有准备特别的调度算法或是内存管理机制来处理线程,而是和进程一样,使用相同的调度算法和内存管理机制。

线程有自己的生命周期,包括创建、就绪、运行、阻塞和终止。线程可以被创建、启动、暂停、恢复和终止。

多个线程共享进程内存,因此需要进行同步以避免数据竞争和冲突。常见的同步机制包括互斥锁、条件变量、信号量和读写锁等,这些机制用于控制线程对共享资源的访问。线程可能引入竞争条件和死锁,需要仔细设计和测试多线程应用。

操作系统负责线程的调度,以确定哪个线程获得CPU时间片执行。调度算法通常以优先级、时间片轮转等方式决定线程执行的顺序。

多线程应用程序对于用户输入和外部事件的响应更快,因为一个线程的阻塞不会影响其他线程的执行。

线程比进程更轻量级,创建和切换开销较小,可以更有效地利用系统资源。

进程间通信方式

进程间通信就是在不同进程之间传播或交换信息。进程间通信的本质就是,让不同的进程看到同一份资源。

匿名管道

shell 命令中的「|」竖线就是匿名管道,通信的数据是无格式的流并且大小受限,通信的方式是单向的,数据只能在一个方向上流动,再来匿名管道是只能用于存在父子关系的进程间通信或者具有共同祖先的进程之间通信

  • pipe 函数用于创建匿名管道
  • 管道只能够进行单向通信,因此当父进程创建完子进程后,需要确认父子进程谁读谁写,然后关闭相应的读写端。

命名管道

命名管道突破了匿名管道只能在亲缘关系进程间的通信限制,因为使用命名管道的前提,需要在文件系统创建一个类型为 p 的设备文件,那么毫无关系的进程就可以通过这个设备文件进行通信。通信数据都遵循先进先出原则。

  • 可以使用 mkfifo 创建一个命名管道。

消息队列

消息队列克服了管道通信的数据是无格式的字节流的问题,消息队列实际上是保存在内核的「消息链表」。消息队列通信的速度不是最及时的,毕竟每次数据的写入和读取都需要经过用户态与内核态之间的拷贝过程。消息队列提供了一种异步通信的机制,所以通信速度不及时!

比如,A 进程要给 B 进程发送消息,A 进程把数据放在对应的消息队列后就可以正常返回了,B 进程需要的时候再去读取数据就可以了。同理,B 进程要给 A 进程发送消息也是如此。

共享内存

共享内存可以解决消息队列通信中用户态与内核态之间数据拷贝过程带来的开销,它直接分配一个共享空间,每个进程都可以直接访问, 而无需数据复制和内核参与。享有最快的进程间通信方式之名。但是便捷高效的共享内存通信,带来新的问题,多进程竞争同个共享资源会造成数据的错乱。

  • 创建共享内存我们需要用 shmget 函数

信号量

那么,就需要信号量来保护共享资源,以确保任何时刻只能有一个进程访问共享资源,这种方式就是互斥访问。信号量其实是一个计数器,表示的是资源个数,其值可以通过两个原子操作来控制,分别是 P 操作和 V 操作

  • 减减的操作就叫做 P 操作,而计数器加加的操作就叫做 V 操作,P操作就是申请信号量,而V操作就是释放信号量。
  • P(等待)操作用于尝试获取资源或者等待某个条件成立,如果资源不可用或条件不成立,则会阻塞。
  • V(发信号)操作用于释放资源或者通知条件成立,如果有其他进程正在等待,则唤醒其中一个。

信号是异步通信机制,一旦有信号发生,进程有三种方式响应信号 1. 执行默认操作、2. 捕捉信号、3. 忽略信号。有两个信号是应用进程无法捕捉和忽略的,即 SIGKILL 和 SIGSTOP,这是为了方便我们能在任何时候结束或停止某个进程。

Socket 通信

Socket 实际上不仅用于不同的主机进程间通信,还可以用于本地主机进程间通信,可根据创建 Socket 的类型不同,分为三种常见的通信方式,一个是基于 TCP 协议的通信方式,一个是基于 UDP 协议的通信方式,一个是本地进程间通信方式。

线程同步机制

用于协调多个线程的执行,以确保数据的正确性和一致性。

互斥锁:

互斥锁是最常见的线程同步机制。它允许多个线程访问共享资源,但在任何给定时刻只有一个线程可以进入临界区(被保护的代码段)。其他线程需要等待锁的释放才能进入临界区。

信号量:

信号量是一种更通用的同步工具,它可以控制同时访问共享资源的线程数量。

条件变量:

条件变量用于在线程之间进行复杂的协调。它通常与互斥锁一起使用,允许线程等待特定条件的发生,并在条件满足时被唤醒。

读写锁:

读写锁允许多个线程同时读取共享资源,但只有一个线程可以写入资源。这对于读多写少的场景非常有用,可以提高性能。

自旋锁

自旋锁是一种锁定机制,它不会使线程休眠,而是在获取锁失败时一直循环尝试,直到成功。自旋锁在短期争用情况下可能效率更高,但需要小心避免长时间的自旋。

守护进程、僵尸进程、孤儿进程

守护进程

是对立于控制终端并且周期性的执行某种任务的进程

指在后台运行的,没有控制终端与之相连的进程。它独立于控制终端,周期性地执行某种任务。Linux的大多数服务器就是用守护进程的方式实现的,如web服务器进程http等

孤儿进程

如果父进程先退出,子进程还没退出,那么子进程的父进程将变为init进程。(注:任何一个进程都必须有父进程)。

一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。

僵尸进程

父进程不读取子进程的退出信息,子进程就会变成僵尸进程,进而造成资源的浪费!

父进程可以使用waitpid来等待子进程的退出,设置WNOHANG为非阻塞等待

如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就成为僵尸进程。

设置僵尸进程的目的是维护子进程的信息,以便父进程在以后某个时候获取。这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间,所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息。如果一个进程终止,而该进程有子进程处于僵尸状态,那么它的所有僵尸子进程的父进程ID将被重置为1(init进程)。继承这些子进程的init进程将清理它们(也就是说init进程将wait它们,从而去除它们的僵尸状态)。

进程一旦变成僵尸进程,kill -9 (SIGKILL)也无法将其杀死,因为谁也无法杀死一个已经死去的进程。

进程/线程切换过程切换的资源有哪些

进程/线程上下文切换是操作系统进行任务切换时,保存当前任务的状态并加载下一个任务的状态的过程。在上下文切换过程中,操作系统需要保存和恢复的资源包括:

寄存器

包括通用寄存器(如PC、SP等)和特殊寄存器(如状态寄存器、控制寄存器等)。保存当前任务的寄存器状态,并加载下一个任务的寄存器状态。

程序计数器(PC)

保存当前任务执行的下一条指令的地址,以便在切换回来时继续执行。

栈指针(SP)

保存当前任务的栈指针,以便在切换回来时继续使用该任务的栈。

内存管理单元(MMU)

保存当前任务的页表、段表等内存管理信息,以便在切换回来时继续使用该任务的内存映射。

文件描述符表

保存当前任务打开的文件描述符信息,以便在切换回来时继续使用。

环境变量

保存当前任务的环境变量信息,以便在切换回来时继续使用。

其他资源

如信号处理函数、定时器、硬件中断等,需要保存当前任务的相关状态,并在切换回来时继续处理。

需要注意的是,不同操作系统和架构可能会有略微不同的上下文切换过程和需要保存的资源,上述列举的是一般情况下的常见资源。

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

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

相关文章

python接口自动化(一)--什么是接口、接口优势、类型(详解)

简介 经常听别人说接口测试,接口测试自动化,但是你对接口,有多少了解和认识,知道什么是接口吗?它是用来做什么的,测试时候要注意什么?坦白的说,笔者之前也不是很清楚。接下来先看一…

Ci2451-2.4g无线MCU收发芯片

Ci2451 是一款集成无线收发器和8位RISC(精简指令集)MCU的SOC芯片。 无线MCU解决方案,集成丰富的MCU资源、更小尺寸,来满足设计中的各种内存、功率、尺寸要求,充分缩短2.4GHz无线产品设计周期并优化产品成本。 添加图片注释,不超过 140 字(可选&#xff…

005:根据股票代码和起始日期获取K线数据

我们改进《001》中的部分,因为他他没法在可视化界面输入信息,这样太麻烦。我们设法在可视化界面输入股票代码和起始日期,这样可以灵活得多。这部分,我们仍旧只获取日K线的数据。 import tkinter as tk from tkinter import messa…

Spring Cloud Gateway实战WebFlux解析请求体及抛出指定错误代码和信息

概述 基于Spring Cloud开发微服务时,使用Spring Cloud原生自带的Gateway作为网关,所有请求都需要经过网关服务转发。 为了防止恶意请求刷取数据,对于业务请求需要进行拦截,故而可在网关服务增加拦截过滤器。基于此,有…

Aruba CX交换机 VSF配置

目前 Aruba CX 交换机中的 6300F 和 6300M 支持 VSF 功能,要求同型号堆叠。 6300 交换机仅仅最后 4 个 SFP56 端口支持 VSF link 6200F : all uplink ports with 10G speed can be configured as VSF link 6200F: VSF allows stacks to be formed using any combin…

【C语言】快速排序

文章目录 一、hoare版本二、挖坑法三、前后指针法四、非递归快排五、快速排序优化1、三数取中选key值2、小区间优化 六、代码测试 一、hoare版本 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素…

蓝桥杯每日一题2023.9.27

4408. 李白打酒加强版 - AcWing题库 题目描述 题目分析 对于这题我们发现有三个变量,店,花,酒的数量,对于这种范围我们使用DP来进行分析。 dp[i][j][k]我们表示有i个店,j朵花,k单位酒的集合&#xff0c…

信息化发展56

数据开发利用 通过数据集成、数据挖掘和数据服务(目录服务、查询服务、浏览和下载服务、数据分发服务)、数据可视化、信息检索等技术手段, 帮助数据用户从数据资源中找到所需要的数据, 并将数据以一定的方式展现出来,…

Databend 源码阅读:配置管理

作者:尚卓燃(PsiACE)澳门科技大学在读硕士,Databend 研发工程师实习生 Apache OpenDAL(Incubating) Committer https://github.com/PsiACE 对于 Databend 这样复杂的数据库服务端程序,往往需要支持大量的可配置选项&am…

PTA程序辅助实验平台——2023年软件设计综合实践_3(分支与循环)

第一题:7-1 印第安男孩 - C/C 分支与循环 朵拉编程的时候也想顺便练习英语。她编程从键盘读入一个整数n,如果n值为0或者1,向屏幕输出“0 indian boy.”或“1 indian boy.”;如果n大于1,比如9,则输出“9 in…

查看Linux系统信息的常用命令

文章目录 1. 机器配置查看2. 常用分析工具3. 常用指令解读3.1 lscpu 4. 定位僵尸进程5. 参考 1. 机器配置查看 # 总核数物理CPU个数x每颗物理CPU的核数 # 总逻辑CPU数物理CPU个数x每颗物理CPU的核数x超线程数 cat /proc/cpuinfo| grep "physical id"| sort| uniq| w…

Jmeter接口自动化和Python接口自动化,如何选择?

选择Jmeter或Python进行接口自动化测试取决于您的具体需求和环境。以下是一些可以考虑的因素: 1. 语言熟悉度:如果您对Java更熟悉,那么Jmeter可能是更好的选择。而如果您的团队或个人对Python更熟悉,那么Python可能是更好的选择。…

Python数据分析之Excel

Openpyxl库 1、Openpyxl模块2、Excel写入2.1、新建2.2、添加数据2.3、单元格格式 3、Excel读取4、Excel的CRUD4.1、查4.2、改4.3、删 1、Openpyxl模块 Openpyxl是一个用于处理xlsx格式Excel表格文件的第三方python库,几乎支持Excel表格的所有操作 基本概念&#x…

GaussDB数据库SQL系列-游标管理

目录 一、前言 二、概述(GaussDB) 1、游标概述 2、游标的使用分类 三、GaussDB中的显式游标(示例) 1、显式游标的使用与操作步骤 2、显式游标示例 四、GaussDB中的隐式游标(示例) 1、隐式游标简介…

MySQL基础进阶

文章目录 MySQL基础进阶 约束 \color{red}{约束} 约束约束的概念和分类约束的概念约束的分类 非空约束概念语法 唯一约束概念语法 主键约束概念语法 数据库设计 \color{red}{数据库设计} 数据库设计软件的研发步骤数据库设计概念数据库设计的步骤表关系一对一一对多&#xff08…

Pytest+Allure+Excel接口自动化测试框架实战

1. Allure 简介 简介 Allure 框架是一个灵活的、轻量级的、支持多语言的测试报告工具,它不仅以 Web 的方式展示了简介的测试结果,而且允许参与开发过程的每个人可以从日常执行的测试中,最大限度地提取有用信息。 Allure 是由 Java 语言开发的…

docker系列文章目录

docker系列专栏笔记总算完成了,平时下班比较晚,利用晚上的一些时间整理了这一系列的学习笔记。 docker系列教程包含以下几个方面: docker环境篇 介绍docker环境的搭建,已经管理平台工具(portainer)的简单使用。 docker常用命令篇…

结构型设计模式——桥接模式

摘要 桥接模式(Bridge pattern): 使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。 一、桥接模式的意图 将抽象与实现分离开来,使它们可以独立变化。 二、桥接模式的类图 Abstraction: 定义抽象类的接口Implementor: 定义实现类接口 …

MySQL 的 C 语言接口

1. mysql_init MYSQL *mysql_init(MYSQL *mysql); mysql_init函数的作用:创建一个 MYSQL 对象(该对象用于连接数据库)。 mysql_init函数的参数: ① mysql:MYSQL 结构体指针,一般设置为 NULL 。 mysql_init函…

实用的 “edge://flags“

~~ edge实验室 ~~ “edge://flags” 是 Microsoft Edge 浏览器中的一个隐藏设置页面,允许用户启用、禁用和调整各种实验性功能和高级选项。这些功能可能会对浏览器的性能和稳定性产生影响,因此使用时需要谨慎。以下是一些实用的 “edge://flags” 设置…