【Linux】初识线程

目录

一、什么是线程:        

重定义线程和进程:

执行流:

Linux中线程的实现方案:

二、再谈进程地址空间

三、小结:

1、概念:

2、进程与线程的关系:

3、线程优点:

4、线程缺点:


一、什么是线程:        

首先我们回顾一下我们之前的进程概念:

如上,首先当我们创建一个进程的时候,就会有对应的task_struct来描述这个进程,如果这个进程正在运行,CPU里面有一个控制寄存器指向该进程,表示该进程在运行

然后我们的task_struct里面有对应的进程地址空间,然后通过页表映射找到对应的物理内存

接着继续创建子进程,子进程会拷贝父进程的task_struct,进程地址空间,然后通过拷贝的页表映射到不同的物理内存中,这样就可以根据不同的进程执行不同的任务了,但是每次切换进程的时候,CPU都要保存原来进程的上下文,重新调度,这样就会显得繁琐,

那么能不能只创建task_struct,然后让新task_struct和旧task_struct都指向同一个进程地址空间,同样,后面的页表也都是一样的了

这样就引入了线程,如下,新创建的task_struct就是一个个线程

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

重定义线程和进程:

那么这就和我们的进程混了,那么就需要重新定义进程了:

从内核视角重新理解进程:进程是承担分配系统资源的基本实体,

进程 = 内核数据结构(task_struct) + 代码和数据,


如上,我们以前的进程并不仅仅是一个task_struct,而是上述蓝框框中的,页表及左边和映射的物理内存,

线程就是系统调度的基本单位,如上的一个个task_struct,这样,操作系统只需要针对task_struct结构即可完成调度

为什么切换线程比切换进程更加轻量化呢?

这里分两个方面:

对于进程或者线程整个生命周期:

1、创建和释放更加轻量化(生死)

2、切换更加轻量化(运行)

我们知道:

进程是有其对应的上下文的,在执行或切换进程时需要保存和恢复的运行时环境信息,以确保进程在重新调度时能继续正确运行,在其进行进程切换的时候,要先保存切换进程的上下文,然后再进行切换,将所有数据都切换(比如与用户空间直接相关的数据和代码资源,CPU寄存器中保存的进程执行状态,内核管理进程所需的控制信息和资源描述)

在CPU内部包括:运算器、控制器、寄存器、MMU、硬件级缓存(cache)等等

其中硬件级的cache又称为高速缓存,遵循计算机设计的基本原则:局部性原理,会预先加载部分用户可能访问的数据以提高效率

当切换进程时,因为存在进程间的独立性,所以cache中的进程数据就要给当前进程保存,然后别的进程再将它自己的可能将要访问的数据加载进cache中,重新开始预加载,这对于CPU是非常浪费时间的

当切换线程时,线程是属于进程的,切换线程时,cache中的数据不用切换,其中的数据可以继续使用,并且可以接着进行预加载机制

cache中的数据被称为缓存的热数据,进程切换使cache中的数据丢失再重新加载,使数据从冷数据重新变为热数据,这是很耗时间的,线程不用切换,直接使用接着预加载,所以线程更加轻量级

执行流:

执行流对应一段代码的运行轨迹,可以大到整个程序(如一个进程),也可以小到一个函数或者代码块(如一个线程)

所以执行流所执行的资源是:线程<=执行流<=进程

当进程中只有一个线程的时候,可以称为当前进程只有个执行流
当进程中有多个线程的时候,称为当前进程有多个执行流,其中每一个执行流就是一个个线程

Linux中线程的实现方案:

在Linux中,线程在进程的“内部”执行,线程在进程的地址空间中运行,因为任何执行流要执行,都要有资源,进程地址空间是进程的资源窗口,进程是承担分配系统资源的基本实体

在Linux中,线程的执行粒度要比进程更细,因为线程是执行进程代码的一部分,线程包含于进程中,所以我们之前学习的进程是不完整的,现在才是完整的

在Linux中,认为进程和线程的共同点很多,于是在写OS对其维护的代码中直接复用了进程的代码,这样就大大减少了系统调度时候的开销,在Linux中没有真正的线程的概念,只有轻量级进程

这种思想使得进程称为一款卓越的操作系统

二、再谈进程地址空间

在如上的图中,我们已经了解了大部分,但是对于页表,我们却是空白的,我们只知道虚拟地址通过页表转化为物理地址,那么具体是怎么实现的呢?

如果是直接地址映射地址的方式:

我们这里以32位系统举例:

在32位系统中:存在2^32大小的地址,这样换算出来就是4GB,这太大了,如今一般配置的电脑内存也才16GB

所以这种方式是不可能的

=========================================================================

在以前的文件系统学习了解到:

OS的读取是以 块 为单位的,一个块的大小是4kb(每个块由8个扇区组成,每个扇区大小为512字节),也就是说即使我们只读1字节,OS也会读4kb

我们的物理内存也是被分为每4kb为一小块的

对于上述的页,我们也要将其管理起来,那么怎么管理呢? ----- 先描述再组织,这样就知道物理内存中的数据是否被占用了,是否存在,是否为脏数据,方便释放管理

=========================================================================

页表的设计逻辑:

依然以我们的32位操作系统为例:

当我们拿到了一个虚拟地址,它会有32个比特位,我们将这32个比特位分成10+10+12,如下:

那么将地址分成3份之后,对应着我们页表也会有3份

以上黑色的对应这页目录,红色的对应着二级页表,蓝色的对应着对应的页框

那么怎么通过这个地址进行虚拟到物理地址之间的转化呢?

首先,将上述对应的三个部位从地址转化为十进制对应的数字

通过前10个比特位,转化的10进制数字找到对应页目录的下标,定位二级页表
然后中10个比特位,转化为10进制数字找到对应二级页表的下标,定位页框地址
最后12个比特位,作为偏移量,也就是通过页框起始地址+偏移量找到对应的物理内存

这样就完成了从虚拟地址到物理地址的转化!

对于上述可能会有一个问题 ----- 那就是如果这个偏移量会不会超过当前页框 ----- 这是不可能的,因为上述偏移量2^12正好是4kb也就是一个页框的大小

那么一个页表多大呢?

在32位操作系统中,我们知道在二级页表中存放的是地址,其中的指针变量,这里按照4字节来算,那么一个页表也就是4*1024*1024字节,那么换算出来就是4MB,这比之前的4GB来说是大大减小了

那么为什么&a只有一个地址呢?

我们知道有类型的存在,所以这里取地址就只会取首地址,然后通过类型转化成偏移量:比如如果是int就向上读取4个字节,char就向上读取1个字节,如果是自定义的类,也是如此
总的来说就是通过 起始地址 + 类型(转化成偏移量) = 读到的数据

三、小结:

1、概念:

Linux中是没有真正线程的概念的,只有轻量级进程(Light-Weight Process, LWP)是进程内的独立执行流,每个线程共享进程的资源(如内存、文件描述符等),但拥有独立的线程ID、寄存器、栈和错误码

2、进程与线程的关系:

在用户视角:

进程是资源分配的实体,而线程是这些资源的使用者
线程共享进程的虚拟地址空间和页表,但拥有独立的PCB(进程控制块)

在内核视角:

Linux内核不严格区分进程和线程,两者均通过clone()系统调用创建。区别在于是否共享地址空间:共享则为线程,独立则为进程

3、线程优点:

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

4、线程缺点:

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

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

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

相关文章

【单片机】ARM 处理器简介

ARM 公司简介 ARM&#xff08;Advanced RISC Machine&#xff09; 是英国 ARM 公司&#xff08;原 Acorn RISC Machine&#xff09; 开发的一种精简指令集&#xff08;RISC&#xff09; 处理器架构。ARM 处理器因其低功耗、高性能、广泛适用性&#xff0c;成为嵌入式系统、移动…

​​《从事件冒泡到处理:前端事件系统的“隐形逻辑”》

“那天在document见到你的第一眼&#xff0c;我就下定决心要陪你到天荒地老” ---React 我将从事件从出现到被处理的各个过程来介绍事件机制&#xff1a; 这张图片给我们展示了react事件的各个阶段&#xff0c;我们可以看到有DOM&#xff0c;合成事件层&#xff0c;还有…

Django小白级开发入门

1、Django概述 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MTV的框架模式&#xff0c;即模型M&#xff0c;视图V和模版T。 Django 框架的核心组件有&#xff1a; 用于创建模型的对象关系映射为最终用户设计较好的管理界面URL 设计设计者友好的模板…

课程《Deep Learning Specialization》

在coursera上&#xff0c;Deep Learning Specialization 课程内容如下图所示&#xff1a;

Java【网络原理】(3)网络编程续

目录 1.前言 2.正文 2.1ServerSocket类 2.2Socket类 2.3Tcp回显服务器 2.3.1TcpEchoServer 2.3.2TcpEchoClient 3.小结 1.前言 哈喽大家好&#xff0c;今天继续进行计算机网络的初阶学习&#xff0c;今天学习的是tcp回显服务器的实现&#xff0c;正文开始 2.正文 在…

安装remixd,在VScode创建hardhat

在终端&#xff0c;以管理员身份&#xff0c;cmd 需要科学上网 npm install -g remix-project/remixd 在vscode插件中&#xff0c;安装solidity插件&#xff0c;是暗灰色那款 1.将nodeJs的版本升级至18以上 2.在vscode打开一个新的文件&#xff0c;在终端输入 npx hardhat 3.…

微服务拆分-远程调用

我们在查询购物车列表的时候&#xff0c;它有一个需求&#xff0c;就是不仅仅要查出购物车当中的这些商品信息&#xff0c;同时还要去查到购物车当中这些商品的最新的价格和状态信息&#xff0c;跟购物车当中的快照进行一个对比&#xff0c;从而去提醒用户。 现在我们已经做了服…

TCP/IP 5层协议簇:网络层(ICMP协议)

1. TCP/IP 5层协议簇 如下&#xff1a; 和ip协议有关的才有ip头 2. ICMP 协议 ICMP协议没有端口号&#xff0c;因为不去上层&#xff0c;上层协议采用端口号

Uniapp 页面返回不刷新?两种方法防止 onShow 触发多次请求!

目录 前言1. 变量&#xff08;不生效&#xff09;2. 延迟&#xff08;生效&#xff09; 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 在 Uniapp 中&#xff0c;使用 onShow() 钩子来监听页面显示&#xff0…

java_了解反射机制

目录 1. 定义 2. 用途 3. 反射基本信息 4. 反射相关的类 4.1 class类&#xff08;反射机制的起源&#xff09; 4.1.1 Class类中的相关方法&#xff08;方法的具体使用在后面的示例中&#xff09; 4.2 反射的示例 4.2.1 获得Class对象的三种方式 4.2.2 反射的使用 Fiel…

基于Python的商品销量的数据分析及推荐系统

一、研究背景及意义 1.1 研究背景 随着电子商务的快速发展&#xff0c;商品销售数据呈现爆炸式增长。这些数据中蕴含着消费者行为、市场趋势、商品关联等有价值的信息。然而&#xff0c;传统的数据分析方法难以处理海量、多源的销售数据&#xff0c;无法满足现代电商的需求。…

P8662 [蓝桥杯 2018 省 AB] 全球变暖--DFS

P8662 [蓝桥杯 2018 省 AB] 全球变暖--dfs 题目 解析讲下DFS代码 题目 解析 这道题的思路就是遍历所有岛屿&#xff0c;判断每一块陆地是否会沉没。对于这种图的遍历&#xff0c;我们首先应该想到DFS。 代码的注意思想就是&#xff0c;在主函数中遍历找出所有岛屿&#xff0c…

tiktok web登录 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向分析 部分代码 response reques…

邮件发送器:使用 Python 构建带 GUI 的邮件自动发送工具

在本篇博客中&#xff0c;我们将深入解析一个使用 wxPython 构建的邮件发送器 GUI 程序。这个工具能够自动查找指定目录中的文件作为附件&#xff0c;并提供邮件发送功能。本文将从功能、代码结构、关键技术等方面进行详细分析。 C:\pythoncode\new\ATemplateFromWeekReportByM…

pyside6学习专栏(十一):在PySide6中实现一简易的画板程序

pyside6学习专栏(十一):在PySide6中实现一简易的画板程序&#xff0c;实现画直线、矩形、填充矩形、圆、椭圆、随手画、文本。为减少代码量&#xff0c;所画形状的颜色、线宽、线型、填充形状、字体、字号等采用随机方式&#xff0c;只作为学习在Python中绘画的基本操作。 主界…

Android 屏幕适配 Tips

概念 屏幕尺寸&#xff1a;屏幕的对角线的长度屏幕分辨率&#xff1a;屏幕分辨率是指在横纵向上的像素点数&#xff0c;单位是px&#xff0c;1px1个像素点。一般以纵向像素x横向像素&#xff0c;如1960x1080屏幕像素密度&#xff1a;每英寸上的像素点数&#xff0c;单位是dpi …

uniapp或者vue 使用serialport

参考https://blog.csdn.net/ykee126/article/details/90440499 版本是第一位&#xff1a;否则容易编译失败 node 版本 18.14.0 npm 版本 9.3.1 electron 版本 30.0.8 electron-rebuild 版本 3.2.9 serialport 版本 10.0.0 需要python环境 main.js // Modules to control app…

从零开始的 Kafka 学习(二)| 集群启动

1. 相关概念 1.1 代理&#xff1a;Broker 使用Kafka前&#xff0c;我们都会启动Kafka服务进程&#xff0c;这里的Kafka服务进程我们一般会称之为Kafka Broker 或 Kafka Server。因为Kafka是分布式消息系统所以再实际的生产环境中&#xff0c;是需要多个服务进程形成集群提供消…

综合使用pandas、numpy、matplotlib、seaborn库做数据分析、挖掘、可视化项目

目录 1.结构化数据挖掘 1.1依赖库导入和数据读取 1.2各品牌机型及售价统计 1.3视频录制规格与价格关联性分析 2.结构化数据预处理 2.1筛选特征 2.2特征标签归一化及编码 1.结构化数据挖掘 1.1依赖库导入和数据读取 导入必要的依赖库&#xff0c;读取 csv 格式数据集转化为 Data…

蓝桥杯题型

蓝桥杯 蓝桥杯题型分类语法基础艺术与篮球&#xff08;日期问题&#xff09;时间显示&#xff08;时间问题&#xff09;跑步计划&#xff08;日期问题&#xff09;偶串(字符&#xff09;最长子序列&#xff08;字符&#xff09;字母数&#xff08;进制转换&#xff09;6个0&…