【多线程】进程与线程

🏀🏀🏀来都来了,不妨点个关注!
🎧🎧🎧博客主页:欢迎各位大佬!
在这里插入图片描述

文章目录

  • 1. 操作系统
    • 1.1 什么是操作系统
    • 1.2 操作系统主要的功能
  • 2. 进程
    • 2.1 什么是进程
    • 2.2 通过PCB描述一个进程
    • 2.3 进程的调度
    • 2.4 PCB的管理
    • 2.5 内存管理
    • 2.6 进程间通信的方式
  • 3.线程
    • 3.1 什么是线程
    • 3.2 有了进程为什么还要有线程
    • 3.3 进程与线程的联系和区别

1. 操作系统

1.1 什么是操作系统

操作系统本质上是运行在计算机上的软件程序,对上,它负责给软件运行提供稳定的环境,对下,它要管理好各种硬件设备。我们可以通过以下的图文进行理解:

在这里插入图片描述

1.2 操作系统主要的功能

从资源管理的角度来看,操作系统主要有六大功能:

  • 进程和线程的管理:进程的创建、撤销、阻塞、唤醒,进程间的通信等。
  • 存储管理:内存的分配和管理、外存(磁盘等)的分配和管理等。
  • 文件管理:文件的读、写、创建及删除等。
  • 设备管理:完成设备(输入输出设备和外部存储设备等)的请求或释放,以及设备启动等功能。
  • 网络管理:操作系统负责管理计算机网络的使用。网络是计算机系统中连接不同计算机的方式,操作系统需要管理计算机网络的配置、连接、通信和安全等,以提供高效可靠的网络服务。
  • 安全管理:用户的身份认证、访问控制、文件加密等,以防止非法用户对系统资源的访问和操作。

可以看到操作系统的上述功能中,进程和线程管理和我们今天要讲的进程与线程关系密切。
那么为什么要进行进程的管理呢,那当然是因为进程太多了才需要管理嘛,就比如我们上学,学校也都有会一个学生管理系统,里面就记录着我们每个学生的信息。下面我们分别从进程和线程两个角度进行讲解。

2. 进程

2.1 什么是进程

一个运行起来的程序就是进程,而我们电脑中的.exe文件就是一个可执行的文件(程序),当双击这个.exe文件,这个程序跑起来就形成了一个进程。关于这个我们可以通过任务管理器查看,如下图:
在这里插入图片描述
在这里插入图片描述
我们从上面两种图都可以观察到我们的计算机上运行着许许多多的进程,我们在最开始提到过,操作系统的一大功能就是进行进程的管理,那么它是如何对进程进行管理的呢?其实就分为两步,下面我们就来介绍:

  1. 描述一个进程:使用结构体/类把一个进程有哪些信息描述出来
  2. 组织这些进程:使用一定的数据结构将这些结构体/对象组织在一起

2.2 通过PCB描述一个进程

在上面我们提到对进程管理分为了两步,第一步就是描述该进程,而在操作系统中,用于描述系统进程状态的数据结构通常被称为进程控制块(Process Control Block, PCB)。而PCB有很多的属性,这里我们将介绍几个核心的:

  1. pid: 进程的唯一身份标识(这个我们在Linux常用命令章节里提到过)
  2. 内存指针:表示当前进程使用的内存是哪一部分(进程要运行起来就需要消耗一些硬件资源,这其中就包括了内存)
  3. 文件描述符表:文件描述符表是一个数据结构,用于记录当前进程打开了哪些文件。当进程需要操作文件时,它会在文件描述符表中分配一个表项,并构造一个结构体来描述该文件的相关信息。
  4. 进程状态:描述当前进程所处的状态
    主要为两个状态:
    就绪态:该进程已经准备好了,随时可以在CPU上运行
    阻塞态:该进程暂时无法在CPU上运行
  5. 进程的优先级:优先级用于决定操作系统调度进程的顺序。优先级高的进程会获得更多的CPU资源
  6. 进程的上下文:进程的上下文就是记录当前进程执行到哪里的"存档记录",进程在离开CPU的时候就需要把进程执行的中间结果进行"存档",等下一次回到CPU上的时候再恢复之前的"存档"。从上一次的结果继续往后面执行。(类似于我们玩游戏玩到一半不玩了进行存档退出,下一次玩的时候再进行读档,回到之前玩的地方继续往后面玩)
  7. 进程的记账信息:统计了每个进程在CPU上执行了多久了,可以作为进程调度的参考依据

其中,第4、5、6,7点都是和进程的调度有关的,下面我们先来介绍一些什么是进程的调度

2.3 进程的调度

在计算机操作系统中,进程调度是指按照某种策略或算法,从就绪队列中选择一个进程,将处理机分配给该进程,使之执行的过程。
那为什么要有进程的调度呢
我们先来了解一下CPU,我们的一个个程序能够运行起来,都是依靠着CPU的调度,我们可以打开任务管理器来看看CPU的相关属性,如下图:
在这里插入图片描述

这个表示我自己计算机的CPU有8个 物理核心,而一个物理核心相当于两个逻辑核心,这表示CPU同时能处理16个任务,此时就有人想问了但我们的计算机上同时运行的进程可不止16个,那CPU是如何处理的呢?这里我们介绍两个核心概念

  • 并行:两个核心同时执行两个任务(进程),此时这两个任务就是并行执行的。
  • 并发: 一个核心先运行进程1运行一会后再运行进程2运行一会后再运行进程3,只有切换的够快,这里的进程1、2,3看起来就像是同时执行的一样。
    这也就告诉我们,虽然我的CPU只能同时执行16个任务,但通过并行+并发,我们就可以同时处理多个任务了,通常我们也将这里的并行+并发统称为并发。

2.4 PCB的管理

操作系统往往是使用双向链表的方式将PCB组织起来,这样进程相当于链表中的节点,方便管理时进行增删改查的操作

  1. 创建一个进程,即创建一个链表的节点
  2. 销毁一个进程,即把链表的节点删除
  3. 遍历进程列表,即遍历链表

2.5 内存管理

操作系统对内存资源的分配,采用的是空间模式 —— 不同进程使用内存中的不同区域,互相之间不会干扰。
而操作系统给每一个进程分配的内存空间都是以“虚拟地址空间”的方式分配的。
这里肯定就会有人要问了,有直接的物理地址,为什么不直接给每一个进程直接分配物理地址。我们用下面进程直接访问实际物理地址的图片来介绍:
在这里插入图片描述

上图就是每个进程都是直接访问物理内存的地址,此时可能就会产生一个比较严重的问题,万一进程1的代码出现了bug(比如数组下标越界,野指针…),可能就会连带着把进程2搞崩溃了。
下面我们就来看看操作系统是如何通过使用虚拟内存来解决这个问题的:
在这里插入图片描述

站在进程自身的角度看,它们的内存地址就是0x00aa-0x00ff,这里访问的内存地址就会被操作系统自动映射到真正的物理地址上,但是进程自身是感知不到实际的物理地址是啥的。
此时如果进程1代码出bug,就没有什么影响,因为任何一个内存操作都需要通过页表翻译,比如出现野指针0x11aa,拿着这个地址,页表无法映射也就不会修改真正物理内存,即不会对进程2的内存数据进行干扰。

  • 页表:操作系统使用页表来维护虚拟地址到物理地址的映射关系。页表是一种数据结构,它记录了每个虚拟页(通常是4KB大小)对应的物理页号。
  • 地址翻译:当CPU执行指令并需要访问某个内存地址时,它首先会检查这个地址是虚拟地址还是物理地址。如果是虚拟地址,CPU会通过页表将其转换为物理地址,然后访问物理内存。
  • 缺页异常:如果CPU在访问某个虚拟页时发现该页没有在物理内存中(即发生了缺页),它会产生一个缺页异常。操作系统会捕获这个异常,并从磁盘或其他存储介质中加载缺失的页到物理内存中,然后更新页表以反映这一变化。

2.6 进程间通信的方式

在上面我们说了操作系统给每个进程都分配了一块独立的虚拟地址空间,这保证了进程间的地址空间隔离。一个进程无法直接访问另一个进程的内存,从而避免了内存冲突和数据损坏。
即各个进程互相之间是无法感受到对方存在的,是相互独立的,这样进程之间互相具备"隔离性",但有时候需要进程之间进行交互,相互配合。
此时就有了进程间的通信:即在隔离性前提下,找一个公共区域,让进程借助这个区域完成数据交换。
目前,主流操作系统提供的进程通信机制有如下:

  1. 管道
  2. 共享内存
  3. 文件
  4. 网络
  5. 信号量
  6. 信号
  7. 套接字(Sockets)

其中,网络是一种相对特殊的 IPC 机制,它除了支持同主机两个进程间通信,还支持同一网络内部非同一主机上的进程间进行通信。

3.线程

3.1 什么是线程

线程(Thread) 也被称为轻量级进程,更加轻量。多个线程可以在同一个进程中同时执行,并且共享进程的资源比如内存空间、文件句柄、网络连接等。举例:你打开的微信里就有一个线程专门用来拉取别人发你的最新的消息。

3.2 有了进程为什么还要有线程

  • 进程切换是一个开销很大的操作,线程切换的成本较低。
  • 线程更轻量,一个进程可以创建多个线程。
  • 多个线程可以并发处理不同的任务,更有效地利用了多处理器和多核计算机。而进程只能在一个时间干一件事,如果在执行过程中遇到阻塞问题比如 IO 阻塞就会挂起直到结果返回。
  • 同一进程内的线程共享内存和文件,因此它们之间相互通信无须调用内核。

3.3 进程与线程的联系和区别

联系:一个进程中可以有多个线程,这些线程共享一份堆和方法区(jdk1.8之后称为元数据区)资源,同时每个线程有自己的虚拟机栈、本地方法栈和程序计数器。这点我们在JVM篇里介绍过。

区别

  1. 进程是操作系统资源分配的基本单位,线程是操作系统调度执行的基本单位(这也告诉我们上述我们介绍的进程的调度,其实是对进程里的线程的调度)
  2. 进程具有独立性,一个进程不会影响另一个进程,但在同一进程的多个线程之间,一个线程挂了,可能会把整个线程带走,影响其它线程。
  3. 进程开销大,消耗资源多,线程执行开销小,但不利于资源的管理和保护

本次的分享就结束了,感谢支持!

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

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

相关文章

jEasyUI 创建菜单按钮

jEasyUI 创建菜单按钮 jEasyUI(jQuery EasyUI)是一个基于jQuery的用户界面插件集合,它为用户提供了一系列的UI组件,如菜单、按钮、表格等,以简化Web页面的开发过程。在本文中,我们将重点介绍如何使用jEasyUI创建菜单按钮。 1. 环境准备 在开始之前,请确保您的开发环境…

使用Python绘制甘特图

使用Python绘制甘特图 甘特图效果代码 甘特图 甘特图是一种项目管理工具,用于展示项目进度和任务安排。它通过条状图形表示各任务的起止时间,便于直观地查看项目的各个任务的进度和相互关系。 效果 [外链图片转存失败,源站可能有防盗链机制,建议将图片…

(void) (_x == _y)的作用

在阅读宋宝华的《Linux设备驱动开发详解》一书时&#xff0c;看到下面这段代码&#xff1a; #define min(x, y) ({ \ const typeof(x) _x (x); \ const typeof(y) -y (y); \ (void) (&_x &_y); \ _x < _y ? _x : _y; }) 这段代码可以理解如…

变量和标识符

一、变量 变量 数据类型 变量名初始值 常量的定义方式 1.#define 宏常量 (Day是常量&#xff0c;一旦修改就会报错) /2.const修饰的变量 #include <iostream> using namespace std; //变量 数据类型 变量名初始值 //常量的定义方式 //1.#define 宏常量 (Day是常量&…

Vue.js 基础入门指南

前言 在前端开发的广阔领域中&#xff0c;Vue.js 无疑是一颗璀璨的明星&#xff0c;以其渐进式框架的特性吸引了无数开发者的目光。Vue.js 旨在通过简洁的 API 实现响应式的数据绑定和组合的视图组件&#xff0c;使得构建用户界面变得既快速又简单。本文将带你走进 Vue.js 的世…

学习探索RASP:下一代应用安全防护技术

在当今数字化浪潮中&#xff0c;各类信息系统、应用程序不仅是企业数字化转型的驱动力&#xff0c;也成为了网络攻击的集中地带。面对日益复杂多变的网络安全威胁&#xff0c;防火墙等传统防护手段逐渐显得力不从心。在此背景下&#xff0c;寻求一种更为智能、高效且能深度融入…

代码随想录算法训练营第22天|LeetCode 77. 组合、216.组合总和III、17.电话号码的字母组合

1. LeetCode 77. 组合 题目链接&#xff1a;https://leetcode.cn/problems/combinations/description/ 文章链接&#xff1a;https://programmercarl.com/0077.组合.html 视频链接&#xff1a;https://www.bilibili.com/video/BV1ti4y1L7cv 思路&#xff1a;利用递归回溯的方式…

Codeforces Round 954 (Div. 3)

这里写自定义目录标题 A. X Axis题意&#xff1a;题解&#xff1a;代码&#xff1a; B. Matrix Stabilization题意&#xff1a;题解&#xff1a;代码&#xff1a; C. Update Queries题意&#xff1a;题解&#xff1a;代码&#xff1a; D. Mathematical Problem题意&#xff1a;…

nanodiffusion代码逐行理解之diffusion

目录 一、diffusion创建二、GaussianDiffusion定义三、代码理解def __init__(self,model,img_size,img_channels,num_classes,betas, loss_type"l2", ema_decay0.9999, ema_start5000, ema_update_rate1,):def remove_noise(self, x, t, y, use_emaTrue):def sample(…

MySQL 集群

MySQL 集群有多种类型&#xff0c;每种类型都有其特定的用途和优势。以下是一些常见的 MySQL 集群解决方案&#xff1a; 1. MySQL Replication 描述&#xff1a;MySQL 复制是一种异步复制机制&#xff0c;允许将一个 MySQL 数据库的数据复制到一个或多个从服务器。 用途&…

bug——多重定义

bug——多重定义 你的问题是在C代码中遇到了"reference to data is ambiguous"的错误。这个错误通常发生在你尝试引用一个具有多重定义的变量时。 在你的代码中&#xff0c;你定义了一个全局变量data&#xff0c;同时&#xff0c;C标准库中也有一个名为data的函数模板…

【云原生】Kubernetes部署高可用平台手册

部署Kubernetes高可用平台 文章目录 部署Kubernetes高可用平台基础环境一、基础环境配置1.1、关闭Swap1.2、添加hosts解析1.3、桥接IPv4流量传递到iptables的链 二、配置Kubernetes的VIP2.1、安装Nginx2.2、修改Nginx配置文件2.3、启动服务2.4、安装Keepalived2.5、修改配置文件…

Linux 定时任务详解:全面掌握 cron 和 at 命令

Linux 定时任务详解&#xff1a;全面掌握 cron 和 at 命令 Linux 系统中定时任务的管理对于运维和开发人员来说都是至关重要的。通过定时任务&#xff0c;可以在特定时间自动执行脚本或命令&#xff0c;提高系统自动化程度。本文将详细介绍 Linux 中常用的定时任务管理工具 cr…

一拖二快充线:生活充电新风尚,高效便捷解决双设备充电难题

一拖二快充线在生活应用领域的优势与双接充电的便携性问题 在现代快节奏的生活中&#xff0c;电子设备已成为我们不可或缺的日常伴侣。无论是智能手机、平板电脑还是笔记本电脑&#xff0c;它们在我们的工作、学习和娱乐中扮演着至关重要的角色。然而&#xff0c;随着设备数量…

优化:遍历List循环查找数据库导致接口过慢问题

前提&#xff1a; 我们在写查询的时候&#xff0c;有时候会遇到多表联查&#xff0c;一遇到多表联查大家就会直接写sql语句&#xff0c;不会使用较为方便的LambdaQueryWrapper去查询了。作为一个2024新进入码农世界的小白&#xff0c;我喜欢使用LambdaQueryWrapper&#xff0c;…

产品经理系列1—如何实现一个电商系统

具体笔记如下&#xff0c;主要按获客—找货—下单—售后四个部分进行模块拆解

代码随想录算法训练Day58|LeetCode417-太平洋大西洋水流问题、LeetCode827-最大人工岛

太平洋大西洋水流问题 力扣417-太平洋大西洋水流问题 有一个 m n 的矩形岛屿&#xff0c;与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界&#xff0c;而 “大西洋” 处于大陆的右边界和下边界。 这个岛被分割成一个由若干方形单元格组成的网格。给定一个…

用 Emacs 写代码有哪些值得推荐的插件

以下是一些用于 Emacs 写代码的值得推荐的插件&#xff1a; Ido-mode&#xff1a;交互式操作模式&#xff0c;它用列出当前目录所有文件的列表来取代常规的打开文件提示符&#xff0c;能让操作更可视化&#xff0c;快速遍历文件。Smex&#xff1a;可替代普通的 M-x 提示符&…

【Unity】unity学习扫盲知识点

1、建议检查下SystemInfo的引用。这个是什么 Unity的SystemInfo类提供了一种获取关于当前硬件和操作系统的信息的方法。这包括设备类型&#xff0c;操作系统&#xff0c;处理器&#xff0c;内存&#xff0c;显卡&#xff0c;支持的Unity特性等。使用SystemInfo类非常简单。它的…

【python】生成完全数

定义 如果一个数恰好等于它的真因子之和&#xff0c;则称该数为“完全数” [2]。各个小于它的约数&#xff08;真约数&#xff0c;列出某数的约数&#xff0c;去掉该数本身&#xff0c;剩下的就是它的真约数&#xff09;的和等于它本身的自然数叫做完全数&#xff08;Perfect …