【Linux】第四十站:线程概念

文章目录

  • 一、线程
  • 二、Linux中线程应该如何理解
  • 三、重新定义线程
  • 四、四谈进程地址空间(页表相关)
  • 五、Linux线程周边的概念
    • 1. 线程与进程切换
    • 2.线程优点
    • 3.线程缺点
    • 4.线程异常
    • 5.线程用途

一、线程

线程:是进程内的一个执行分支。线程的执行粒度,要比进程要细

  • 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”
  • 一切进程至少都有一个执行线程
  • 线程在进程内部运行,本质是在进程地址空间内运行
  • 在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化
  • 透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流

二、Linux中线程应该如何理解

如下图所示的内容,我们都是可以理解的

image-20240227182959872

我们可以注意到,我们进程所能看到的资源都是通过地址空间+页表才能看到的。

所以地址空间是进程的资源窗口

而进程的独立性是,当我们创建好一个子进程的时候,他们就有了不同内核数据结构,他们就可以映射到不同的物理地址中

image-20240227183402212

如果我们再创建一个进程,并且它不创建新的地址空间。而是去共享地址空间,直接把原来地址空间中的一部分给他,并且和内存建立映射

image-20240227184003058

那么这些进程它的执行粒度就更细了,因为它只执行那一点点,我们将这样的进程称为线程

Linux的具体的实现线程的方案:

  1. 再linux中,线程在”进程内部“执行,线程在进程的地址空间内运行(为什么?)

    我们知道任何执行流要执行,都要有资源!进程空间是进程的资源窗口。

  2. 在linux中,线程的执行粒度要比进程更细,代码执行进程代码的一部分

    进程它访问的时候更粗犷一些,而线程是比较细一些的

    在CPU看来,它不知道也不需要知道哪个task_struct是进程还是线程。

    CPU只有调度执行流的概念

在不通过的平台中,实现线程的方案各有不同。

三、重新定义线程

什么叫做线程?

  • 我们认为线程是操作系统调度的基本单位

起初我们认为进程=内核数据结构(task_struct) + 代码和数据

上面的当然是正确的。

其实:像下面的红色框所圈的部分,这才是进程!,进程 = 一大堆的执行流+进程地址空间+页表+在物理内存中所占据的代码和数据

image-20240227190148635

所以我们可以重新理解进程:

内核观点:进程是承担分配系统资源的基本实体

那么执行流是资源吗?当然是的!

所以线程和进程的关系就是,进程是包含线程的

因为进程是承担分配系统资源的基本实体

而线程是内部的执行流资源

如何理解,我们以前谈的这个进程?(下图的)

image-20240227190723565

操作系统以进程为单位,给我们分配资源,只不过我们当前的进程内部,只有一个执行流!

在我们的系统中,进程:线程一定是1:n的,至少也是1:1。所以linux系统中线程一旦躲起来,它也要进行管理。所以还是我们曾经说的那六个字 先描述,在组织,它也是要管理线程的

在大部分的教材中,存在一个tcb

struct tcb;//therad ctrl block

所以就需要创建tcb之后,然后将他们组织起来

而windows就这样干了,就是为每个线程创建tcb,然后把进程和线程管理起来

而对于linux系统,它直接复用了进程数据结构和管理算法。使用下面的去模拟线程

struct task_struct //模拟线程

所以Linux没有真正意义上的线程而是用”进程“(用它的内核数据结构)模拟的线程

那么windows的方案还是linux的方案。那么更好呢?

当然那是linux中的,因为像如果专门设计一个tcb的话,那么中间必然有大量的相似的代码,就会导致它的维护成本直线上升。它的健壮性就不够好了。

所以其实linux有线程,不过它没有真正意义上的线程罢了。它用的是进程的数据结构去模拟的线程(进程还包括代码和数据,这里我们只用内核数据结构)

站在我们CPU的视角上,CPU无法区分是线程还是进程

但是在在CPU的视角线程(tcb)<=执行流(进程模拟的线程)<=进程

我们将Linux当中的执行流,称之为轻量级进程

举个例子,在我们的家庭中。我们的每个人都有自己的任务,我们要学习,父母要赚钱,爷爷奶奶要养好身体。所有人都有自己的任务,但是所有人的共同目标是将家里的日子过好。这个家就是一个进程,而每个人就是一个线程。而进程中的哪些其他资源都是给这些对应的执行流的。

而我们的创建进程,就需要创建这些资源,其实就好比买房买车

四、四谈进程地址空间(页表相关)

如何理解资源分配给线程??


如下图所示,是我们曾经所提及的内容,CPU中一个CR3寄存器指向页表,还有一个寄存器指向task_struct,物理内存也是被划分为一个个的也页框,磁盘中的可执行程序也是按照4KB的大小放的

image-20240228152541018

而4KB其实就是2^12


虚拟地址是如何转换到物理地址的???

当我们将物理地址读到CPU的时候,这里是虚拟地址

image-20240228154305815

我们这里以32位计算机虚拟地址为例

虚拟地址就是32位的。其实这个32位的虚拟地址不是一个整体:而是10 + 10 +12

其次页表也不是一整块的。如果它是整块的,假设我们页表的一行是10个字节(它至少也有四个字节的虚拟地址,四个字节的物理地址,还有一些其他的标志位,我们这里为了方便计算,就按10字节来计算)

如果我们的页表是满的话,它有2^32次方个条目,每行10字节,总共需要40GB!

我们会发现,整个内存全放页表都放不下,更何况这只是一个页表,所以计算机中肯定不可能是页表是一整块的

其实32位是被拆成两级的

第一级页表是1024个条目。每一个条目,还存放另一个二级页表,而每个二级页表也有1024个条目。如下图所示是页表的真实面目

image-20240228164902379

我们可以来计算一下此时的页表有多大

一个二级页表假设每一个页表表项是4字节,那么它一共是4KB。其实这刚好是一个页框。而他一共最多有1024个二级页表。所以是4MB

它相比上面的结构,已经大大减少了内存了。而且二级页表也不一定是全部存在的,大部分情况下二级页表都是不全的。

所以创建一个进程其实依旧是一个”很重“的工作

现在我们已经找到了这个数据的地址了。可是我们访问的时候访问的是4个字节等。这如何找到呢?所以这里就需要用类型了,它会认识这个int。然后就会取出四个字节。这些类型是给CPU看的,CPU就知道了读取几个字节了。

起始地址+类型==>起始地址+偏移量

image-20240228172029332


所以如何理解资源分配呢?

线程分配资源的本质,本质是分配地址空间范围

五、Linux线程周边的概念

1. 线程与进程切换

我们知道线程比进程要更轻量化(为什么?)

  1. 创建和释放更加轻量化(创建线程只需要创建tcb,进程还有一堆进程地址空间,页表等…)
  2. 切换更加轻量化(运行时,页表等不需要切换)

整个生命周期都是更加轻量化的

线程的执行本质就是进程的执行,因为线程是进程的一个分支

所以CPU内还有一个硬件级别的缓存:Cache(它里面就是一些缓存的热数据)

CPU在切换线程的时候,上下文虽然一直在变化,但是缓存一直不变,或者在少量更新。而进程切换的时候,它的这些Cache里面的热数据都要被丢弃掉,重新缓存新的数据。所以进程内的线程切换时,Cache内的数据不需要重新缓存。

那么我们怎么知道当前切换的线程是进程被切换了,还是一个线程内的被切换了。所以我们需要对每个线程作一个标识,第一个创建的线程是主线程,其他的线程就是新线程

image-20240228172150238


2.线程优点

  • 创建一个新线程的代价要比创建一个新进程小得多
  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多
  • 线程占用的资源要比进程少很多
  • 能充分利用多处理器的可并行数量
  • 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

3.线程缺点

  • 性能损失
  • 一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度开销,而可用的资源不变。
  • 健壮性降低
  • 编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。
  • 缺乏访问控制
  • 进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。
  • 编程难度提高
  • 编写与调试一个多线程程序比单线程程序困难得多

4.线程异常

  • 单个线程如果出现除零,野指针问题导致线程崩溃,进程也会随着崩溃
  • 线程是进程的执行分支,线程出异常,就类似进程出异常,进而触发信号机制,终止进程,进程终止,该进程内的所有线程也就随即退出

5.线程用途

  • 合理的使用多线程,能提高CPU密集型程序的执行效率
  • 合理的使用多线程,能提高IO密集型程序的用户体验(如生活中我们一边写代码一边下载开发工具,就是多线程运行的一种表现

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

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

相关文章

Linux mmap系统调用

文章目录 前言一、mmap()函数简介二、代码演示2.1 mmap使用场景2.2 私有匿名映射2.3 私有文件映射2.4 共享匿名映射2.5 共享文件映射 参考 前言 NAMEmmap, munmap - map or unmap files or devices into memorySYNOPSIS#include <sys/mman.h>void *mmap(void *addr, siz…

跨境电商趋势解析:社交电商携手私域流量运营,精准触达与转化

随着全球化的深入发展&#xff0c;跨境电商逐渐成为全球贸易的重要组成部分。在这一背景下&#xff0c;社交电商作为一种新兴的商业模式&#xff0c;正逐渐在跨境电商领域崭露头角&#xff0c;并对私域流量的运营产生了深远的影响。本文Nox聚星将和大家分析社交电商在跨境电商中…

浏览器一键重新发起请求

一、需求场景 在前端开发过程中&#xff0c;经常会需要重新请求后台进行代码调试&#xff0c;之前的常规方法是刷新浏览器页面或者点击页面进行交互&#xff0c;这样对多个请求的场景就很方便&#xff0c;但是往往很多时候我们只是单纯的想重新发起一个请求&#xff08;多个请求…

力扣---接雨水---单调队列

题目&#xff1a; 单调队列思想&#xff1a; 没有思路的小伙伴可以先把这个想清楚哦&#xff1a;力扣hot10---大根堆双端队列-CSDN博客 从上面的图就可以发现&#xff0c;如果柱子呈递减序列&#xff0c;那么不会接到雨水&#xff0c;只要有一个小凸起柱子&#xff0c;那么这个…

PubMedQA数据集分享

来源: AINLPer公众号&#xff08;每日干货分享&#xff01;&#xff01;&#xff09; 编辑: ShuYini 校稿: ShuYini 时间: 2024-2-28 该数据集由匹兹堡、卡内基梅隆等大学提出&#xff0c;它是第一个需要对生物医学研究文本进行推理&#xff0c;特别是其定量内容的问答数据集。…

【前端】-初始前端以及html的学习

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

Vue开发实例(八)Vuex状态管理store

Vuex状态管理store 一、Vuex的安装与配置二、store使用方法1、基础使用2、提交变更3、getters使用4、在其他页面&#xff08;组件&#xff09;中显示5、modules多模块 做vue项目的时候&#xff0c; store状态管理器可以帮助我们完成一些数据的存储和管理&#xff0c;通俗理解是…

如何将任何文本转换为概念图(GC)

原文地址&#xff1a;how-to-convert-any-text-into-a-graph-of-concepts 使用 Mistral 7B 将任何文本语料库转换为知识图的方法 2023 年 11 月 10 日 使用递归 RAG 方法来实现具有多跳推理的 QnA&#xff0c;以回答基于大型文本语料库的复杂查询。 知识图增强生成与递归 R…

unity-urp:视野雾

问题背景 恐怖游戏在黑夜或者某些场景下&#xff0c;需要用雾或者黑暗遮盖视野&#xff0c;搭建游戏氛围 效果 场景中&#xff0c;雾会遮挡场景和怪物&#xff0c;但是在玩家视野内雾会消散&#xff0c;距离玩家越近雾越薄。 当前是第三人称视角&#xff0c;但是可以轻松的…

【C++】十大排序算法之 归并排序 快速排序

本次介绍内容参考自&#xff1a;十大经典排序算法&#xff08;C实现&#xff09; - fengMisaka - 博客园 (cnblogs.com) 排序算法是《数据结构与算法》中最基本的算法之一。 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a;通过比较来决定元素间的相对次序…

力扣--滑动窗口438.找到字符串中所有字母异位词

思路分析&#xff1a; 使用两个数组snum和pnum分别记录字符串s和p中各字符出现的次数。遍历字符串p&#xff0c;统计其中各字符的出现次数&#xff0c;存储在pnum数组中。初始化snum数组&#xff0c;统计s的前m-1个字符的出现次数。从第m个字符开始遍历s&#xff0c;通过滑动窗…

史上最细,接口自动化测试用例设计编写总结,一篇带你打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 说到自动化测试&a…

亚信安慧AntDB:“融合+实时”引领数据库创新

在当今多变的数据应用场景中&#xff0c;AntDB作为行业领先的超融合流式实时数仓&#xff0c;秉承着“融合实时”的研发理念&#xff0c;全面应对企业日益复杂的数据处理需求。通过SQL接口访问多种执行引擎&#xff0c;AntDB在实现交易、分析等多重能力的“超融合”方面取得了显…

SQL设计时增加说明列

后关闭sql Studio,然后打开注册表,注册表地址: 计算机\HKEY_CURRENT_USER\SOFTWARE\Microsoft\SQL Server Management Studio\18.0_IsoShell\DataProject 如有版本不同,红色内容有所变化,修改内容如下: SSVPropViewColumnsSQL70,SSVPropViewColumnsSQL80 全修改为 1,2,6,7…

魔方,3循环是你的秘密[嗑瓜子]。​

引理1.任意Sn中的元素&#xff1a;(N_1N_2N_3...N_m) 证明&#xff1a; (N_1N_2N_3...N_m) (N_1N_m)(N_1N_m-1)...(N_1N_2) 举例&#xff1a; 比如(1234) (14)(13)(12) (3214) (34)(31)(32) 2.任意An可以表示成3循环的乘积&#xff0c; 证明&#xff1a; 1.An中的元素属于…

抖店无货源模式,采购商品、平台渠道正规吗?相关基础问题解答

我是王路飞。 无货源模式&#xff0c;相信你们也都不陌生了。 每个电商平台都存在这种模式&#xff0c;且我以为&#xff0c;每个电商平台的发展壮大&#xff0c;最应该感谢的就是这些无货源商家了。 而现在说到无货源&#xff0c;最适合普通人的无疑就是抖音小店了。 今天…

[云原生] k8s之存储卷

一、emptyDir存储卷 当Pod被分配给节点时&#xff0c;首先创建emptyDir卷&#xff0c;并且只要该Pod在该节点上运行&#xff0c;该卷就会存在。正如卷的名字所述&#xff0c;它最初是空的。Pod 中的容器可以读取和写入emptyDir卷中的相同文件&#xff0c;尽管该卷可以挂载到每…

【Redis】redis持久化

redis 持久化 所谓的持久化&#xff0c;就是把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。 redis 开始是将所有数据保持在内存中&#xff0c;对数据的更新将根据策略配置异步地保存在磁盘中。 持久化的方式 快照方式 快照是某时某刻对数据的完整备份。在以…

3dmax画图卡顿解决方法---模大狮模型网

当你在使用3D Max进行画图时遇到卡顿问题&#xff0c;可以尝试以下方法来解决&#xff1a; 减少模型复杂度&#xff1a;如果你的场景中有过多的高细节模型&#xff0c;可能会导致卡顿。尝试减少模型的复杂度&#xff0c;合并或简化多边形数量过多的模型。这将减轻计算机的负担&…

【UE 材质 Niagara】爆炸效果

目录 效果 步骤 一、材质部分 二、Niagara部分 效果 步骤 一、材质部分 1. 创建一个材质&#xff0c;这里命名为“M_Burst” 打开“M_Burst”&#xff0c;设置混合模式为半透明&#xff0c;设置着色模型为无光照&#xff0c;勾选双面显示 在材质图表中首先创建扰动效果 其…