Linux之多线程(上)——Linux下的线程概念

news2024/11/28 18:36:18

文章目录

  • 前言
  • 一、地址空间和页表
    • 1.二级页表
    • 2.例子
  • 二、线程
    • 1.概念
      • 重新理解前面讲的进程:在内核的视角,进程是承担分配系统资源的基本实体。
      • 站在CPU角度,能否去识别当前调度的task_struct是进程还是线程?
      • Linux下并不存在真正的线程
      • 总结
    • 2.线程的优点
    • 3.线程的缺点
      • 健壮性降低的例子
    • 4.线程的异常
    • 5.线程的用途
  • 三、Linux下的进程与线程
    • 进程的多个线程共享的资源
    • 线程独立的数据
    • 进程与线程的关系
  • 总结


前言

本文介绍了地址空间和二级页表、Linux下的线程、线程的优缺点以及线程与进程的关系等概念。


一、地址空间和页表

地址空间是进程能看到的资源窗口:一个进程可以看到代码区、堆栈区、共享区、内核区等,大部分的资源是在地址空间上看到的。
页表决定进程真正有用资源的情况:进程认为自己独占系统的4GB资源,但实际上进程拥有多少物理资源是由页表决定的。
合理的对地址空间和页表进行资源划分,我们就可以对进程所拥有的资源进行分类:通过地址空间的区域划分,划分为栈区、堆区……,通过页表映射到不同的物理内存中。

1.二级页表

在32位平台下,一共有2^32个地址,这也意味着有2^32个地址需要被映射。
地址空间有2^32个地址,每个地址单位都是1字节,页表也要有2^32个条目(每个地址都要经过页表映射,它们都是页表的条目),包括是否命中,包括RWX权限,包括U/K权限。一个条目假设有6个字节的数据,那么光保存页表的空间就需要24GB(4GB大约40亿字节)。
在这里插入图片描述
每个表项中处理要有虚拟地址和它映射的物理地址外,时间还需要一些权限相关的信息,用户级页表和内核级页表实际就是通过权限进行区分。
在这里插入图片描述
虚拟地址:32位下是32位。
物理地址:被划分为一块块的数据框。
OS要对物理内存进行管理:先描述(结构体:struct Page{//内存的属性——4KB}),再组织(数组:struct Page mem[])。
在OS中把物理内存一块块的数据框称为页框,磁盘上编译形成可执行程序的时候被划分为一个个4KB的区域称为页帧。当内存和磁盘进行数据交换时,也是以4KB大小为单位进行加载和保存的。
因此,将数据加载到内存时,在文件系统级别需要按照4KB为基本单位将数据从外设搬到内存。最后,OS系统想要管理内存,除了结构匹配还要有管理算法Linux常见的管理算法称为伙伴系统

虚拟地址转化为物理地址:虚拟地址形成后(以10,10,12的二进制构成),页表不止一张。第一级页表页目录:前十个在页目录中查找,2^10个指向页表的内容。页表:页表的条目项为2^10个,条目写的是指定页框的起始物理地址,页表项指向物理内存中某一页,剩下的12位虚拟地址刚好与页框的大小是等价的(4KB = 2^12B),因此,从物理地址的起始处 + 虚拟地址的低12位(2^12偏移量)作为页内偏移,就可以直接在某个页内找到某个地址。
在这里插入图片描述
其中的页目录项是一级页表,页表项是二级页表。映射过程由MMU这个硬件完成(该硬件集成在CPU内),页表是一种软件映射,MMU是一种硬件映射,虚拟地址转为物理地址实际上是软硬件结合的。

2.例子

修改常量字符串为什么会发送错误?
如果要修改一个常量字符串,虚拟地址需要经过页表映射查找到对应的物理内存,但是在查表的过程中会发现该地址的权限是只读,对一个只读地址进行修改会导致在MMU内部触发硬件错误,OS识别到这个错误会该对应进程发送信号终止对应进程。

二、线程

1.概念

  1. 在一个程序里的一个执行路线就叫做线程(可以参考进程)。更准确的定义是:线程是一个进程内部的控制序列
  2. 一切进程都至少有一个执行线程。
  3. 线程在进程内部运行本质是在进程的地址空间内运行。
  4. Linux中,在CPU眼中看到的PCB都比传统的进程更加轻量化。
  5. 透过进程的虚拟地址空间可以看到进程的大部分资源,将进程的资源合理分配给每个执行流,就形成了线程执行流。
  6. 不同平台的多线程底层实现策略都是不同的,本文我们了解的是Linux下的多线程策略。

线程对应的模型:进程的创建实际上伴随着进程控制块(PCB)、进程地址空间(mm_struct)以及页表的创建(虚拟地址和物理地址是通过页表建立映射的):
在这里插入图片描述
进程 = 内核数据结构 + 代码和数据。
每个进程都有字节独立的进程地址空间和独立的页表,这意味着每个进程在运行时会具有独立性,
如果我们在创建进程时只创建进程的PCB,并要求创建出来的PCB不再独立创建资源,而是与父进程共享资源。那么创建的结果就是下面这样的:

因为我们可以通过虚拟地址空间 + 页表的方式对进程的资源进行划分,单个进程的执行力度会比之前的进程更细。
上图中每个线程都是当前进程的一个执行流,线程在进程的内部运行,在进程的地址空间运行,拥有该进程的一部分资源。

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

创建进程时,申请的PCB、虚拟内存空间、页表以及加载到物理内存中的代码和数据:花费CPU资源创建进程并初始化;花费内存资源保存进程的内核数据结构、代码和数据;花费CPU的IO资源从外设IO到内存。所以承担分配系统资源的基本实体是进程。
总结一下,我们创建进程时,OS申请一堆的内核数据结构占用资源,进程的代码和数据加载到内存中也要占用资源,以及其他部分占用的资源。因此,进程是承担系统资源分配的基本实体。
我们之前讨论的进程都是只有一个PCB,也就是说该进程内部只有一个执行流,即单执行流,这与我们上面讲的并不冲突,如果是像上面这样的一个进程内部由多个执行流,那它就是多执行流进程。

站在CPU角度,能否去识别当前调度的task_struct是进程还是线程?

不能,也不需要,CPU不关心当前调度的是进程还是线程。CPU以task_struct为单位进行调度,今天我们喂给CPU的task_struct是小于等于过去所说的task_struct的,它比之前的更轻量化。因此,在Linux中可以把进程和线程做一个统一,CPU看到的task_struct称为轻量级期间进程。
在Linux中,什么是线程?——线程是CPU的基本调度单位

Linux下并不存在真正的线程

Linux下的线程是用进程模拟的。
如果OS真正要专门设计“线程”概念,OS就要管理线程了(先描述,再组织)。
Windows下确实是为线程专门设计了数据结果表示线程对象TCB,但是线程的创建就是为被执行,执行需要被调度、存在ID/状态、优先级、上下文、栈……等内容,这些线程调度需要的东西与进程有很多地方是重叠的。因此,Linux下没有为“线程”专门设计对应的数据结构,而是直接复用了进程的PCB,用PCB来表示Linux下的“线程”

总结

  1. Linux内核中严格来说是没有真正意义的线程的,Linux用进程PCB来模拟线程,它有一套完全属于自己的线程方案。
  2. 站在CPU角度,每一个PCB都可以称为轻量级进程。
  3. Linux下,线程是CPU调度的基本单位,进程是承担分配系统资源的基本单位。
  4. 进程用来整体申请资源,线程是伸手向进程要资源。(所以线程在执行时申请的资源,实际上是进程向系统申请的资源)
  5. 进程模拟线程的好处:用PCB模拟线程,则为PCB编写的结构和算法都可以进行复用,不用单独再为线程创建结构和调度算法,降低了系统的维护成本,同时复用进程的那套,可靠高效

2.线程的优点

  1. 创建一个线程要花费的代价比创建一个进程的代价要小得多,与进程切换相比,线程之间的切换需要操作系统做的工作要少很多。
    进程切换:要切换页表、虚拟地址空间、PCB、上下文;
    线程切换:切换PCB和上下文。
  2. 线程占用的资源要比进程占用的资源少很多。
  3. 线程能充分利用多处理器的可并行数量。
  4. 在等待慢速I/O操作结束的同时,程序可执行其他计算任务。
  5. 计算密集型应用(CPU、加密、解密、算法等),为了能在多处理器系统上运行,可以讲计算分解到多个线程中实现。
  6. I/O密集型应用(外设、磁盘、显示器、网络),为了提高性能,讲I/O操作重叠,使线程可以同时等待不同的I/O操作。

3.线程的缺点

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

健壮性降低的例子

一个线程如果出现了异常会影响其他线程(健壮性、鲁棒性较差)

  1 #include<iostream>
  2 #include<string>
  3 #include<unistd.h>
  4 #include<pthread.h>
  5 using namespace std;
  6 void* start_routine(void* args)
  7 {
  8         string name = static_cast<const char*>(args);//安全的进行强制类型转换
  9         while(1)
 10         {
 11                 cout<<"new thread create success, name:"<<name<<endl;
 12                 sleep(1);
 13                 int* p = nullptr;
 14                 *p = 0;
 15         }
 16 }
 17 int main()
 18 {
 19         pthread_t id;
 20         pthread_create(&id, nullptr, start_routine, (void*)"thread new");
 21         while(1)
 22         {
 23                 cout<<"new thread create success, name: main thread"<<endl;
 24                 sleep(1);
 25         }
 26         return 0;
 27 }

运行:
在这里插入图片描述

线程出现异常会影响其他线程,这是因为信号是由OS发送给整个进程的,当前线程出现异常,那么OS识别到当前硬件报错、地址转化出现失败、没有权限的空间进行写入、MMU+页表执行异常等问题,OS会立即识别是哪个线程/进程出错,而所有的线程的PID是相同的,因此OS会直接给所有该PID的线程的PCB写入11号段错误信号,这就终止了当前的进程执行流,当前进程就退了,而线程所拥有的资源是进程给的,进程没了,线程也就得退出了。

4.线程的异常

当线程如果出现除零、野指针问题,会导致当前线程崩溃,进程也会随之崩溃。线程是进程的执行分支,线程出现异常,就等同于进程出现异常,进而触发信号机制,终止进程。进程终止了,进程内运行的所有线程也就终止了。

5.线程的用途

  1. 合理使用多线程,可用提高CPU密集型程序的执行效率;
  2. 合理使用多线程,可用提高IO密集型程序的用户体验(例如,我们一边写代码,一边下载开发工具,就是多线程运行的一种表现)

三、Linux下的进程与线程

进程是承担分配系统资源的基本实体,线程是系统调度的基本单位。

进程的多个线程共享的资源

  1. 因为这些线程在同一个地址空间,所以代码段(Text Segment)、数据段(Data Segment)都是共享的。
  2. 如果是函数,那么在各个线程内都是可用调用的;如果是变量,那么在各个线程中都可以访问到。
  3. 线程还贡献一下进程资源和环境:
    文件描述符表、每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)、当前的工作目录、用户id和组id。

线程独立的数据

进程内的线程共享进程的数据,但是也拥有自己独立的一部分数据。
线程ID、一组寄存器:存储线程的上下文信息、栈:线程的临时数据、errno、信号屏蔽字、调度优先级。

进程与线程的关系

在这里插入图片描述
我们之前接触到的只有一个线程执行流的进程,就是单线程进程。


总结

以上就是今天要讲的内容,本文介绍了本文介绍了地址空间和二级页表、Linux下的线程、线程的优缺点以及线程与进程的关系等概念。本文作者目前也是正在学习Linux相关的知识,如果文章中的内容有错误或者不严谨的部分,欢迎大家在评论区指出,也欢迎大家在评论区提问、交流。
最后,如果本篇文章对你有所启发的话,希望可以多多支持作者,谢谢大家!

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

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

相关文章

漫谈程序员创业

很多程序员选择辞职创业&#xff0c;成为了自己公司的创始人或者合伙人。他们选择离开原有的公司&#xff0c;是因为想要实现自己的梦想&#xff0c;追求更高的创业成就。辞职创业是一项具有挑战性的决定&#xff0c;需要勇气、决心和毅力。一些成功的创业者通过坚持不懈和不断…

知乎视频发布软件使用方法视频

知乎视频发布软件使用方法视频&#xff0c;知乎批量发布软件效果怎么样 #小红书视频上传#抖音seo软件#网络推广#视频营销 软件有月卡、季卡、半年卡、年卡 【其中推荐&#xff1a;百家号 哔哩哔哩B站&#xff0c;微博等软件发帖】 服务时间&#xff1a;&#xff08;8&#xf…

Win10 IE11浏览器,您正在查看的页使用 Java,Microsoft 网站提供有关 Java 支持的更多信息 解决

最近工作需要支持下IE11浏览器&#xff0c;使用java applet控件。 以前IE10及以下版本都比较正常&#xff0c;但是IE11会出现一些比较奇怪的现象。 记录下解决的方法和过程&#xff0c;便于有需要的同学自取。 1.首先是报错&#xff0c;如下图所示&#xff1b;这个网上搜索了…

B站热点预测,提前解码流量关口

“追热点”是创作者的必修课。互联网信息更迭迅速&#xff0c;热点千变万化&#xff0c;今天是这个明天可能就不热了&#xff0c;或者敏锐度不够的创作者甚至会错过最佳进场时期&#xff0c;反倒蹭了热点但只抹到一点奶油。 与此同时&#xff0c;还很考验创作者对热点的发散性…

Layui禁止表格部分复选框,layui禁止表格自带第一列复选框,layui禁止表格部分复选框,layui获取表格复选框选中数据

前言 禁止某些行可以勾选操作&#xff0c;及选中后的操作和行操作 效果 实现 执行一个table示例 <table id"data_table" class"layui-hide" lay-filter"data_table"></table>cols 的第一列就是需要重写的复选框 table.render({…

为什么针对API的Bot自动化攻击越来越多?

API是连接现代应用程序的基石&#xff0c;越来越多的企业意识到API的重要性&#xff0c;其数量迎来爆发式增长&#xff0c;但API面临的安全威胁却比API调用增长更加迅猛。Salt Security于今年2月发布的报告显示&#xff0c;2022年有91%的公司存在与API相关的安全问题&#xff0…

门禁巨头遭勒索攻击,北约、阿里集团等多个实体受到影响

Cyber News 网站披露&#xff0c;疑似与俄罗斯有关的勒索软件团伙 ALPV/BlackCat 袭击了安全门禁制造商Automatic Systems&#xff0c;北约、阿里巴巴、泰雷兹等多个实体组织可能受到影响。 攻击事件发生后&#xff0c;ALPV/BlackCat 在暗网泄露网站上发布了安全门禁制造商 Aut…

基于Citespace、vosviewer文献计量学发表的论文-让您增加一条轻松搞定SCI论文途径

Citespace和vosviewer是使用最广泛的文献信息可视化软件工具&#xff0c;在理工、经管、法学、教育、农学、文史、医学、艺术等学科中普遍应用&#xff0c;发文量逐年显著上升。理论与实践相结合&#xff0c;通过文献计量学讲解、高效选题、数据库检索数据下载、软件使用等八个…

实战项目!ModbusRTU协议电磁泵驱动器温控器通讯讲解

大家好&#xff0c;我是华山自控编程的朱老师。 在之前的网课中&#xff0c;我们已经讲解了以下内容 1.C#与PLC的串口通讯 2.C#与变频器的通讯 3.C#的服务器和客户端的网络通讯 今天&#xff0c;我要视频和大家分享的是关于C#与我们的电磁泵驱动器以及C#与温控器的Modbus通…

微服务: 01-rabbitmq的应用场景及安装(docker)

目录 1. rabbitmq前言简介: 1.1 RabbitMQ的几个重要作用&#xff1a; -> 1.1.1 解耦&#xff1a; -> 1.1.2 异步通信&#xff1a; -> 1.1.3 流量削峰&#xff1a; -> 1.1.4 消息传递的可靠性和持久性&#xff1a; 2. rabbitmq的安装(docker版) -> 2.1 …

主动数据安全方法及最佳实践

数据安全管理不能只是为了限制组织中数据的使用&#xff0c;也不能仅仅是提供组织内数据出现泄露甚至是组织因数据安全受到监管惩罚后的解决方案。数据安全管理需要更有效地促进组织内数据资产的流通&#xff0c;并最大限度地避免数据安全事故。 一、为什么需要数据安全管理&a…

声音克隆,精致细腻,人工智能AI打造国师“一镜到底”鬼畜视频,基于PaddleSpeech(Python3.10)

电影《满江红》上映之后&#xff0c;国师的一段采访视频火了&#xff0c;被无数段子手恶搞做成鬼畜视频&#xff0c;诚然&#xff0c;国师的这段采访文本相当经典&#xff0c;他生动地描述了一个牛逼吹完&#xff0c;大家都信了&#xff0c;结果发现自己没办法完成最后放弃&…

【涨粉秘籍】如何快速涨粉并转化为铁粉。

如何快速涨粉并转化为铁粉。 前言在这一百天里&#xff0c;我在csdn获得了什么如何100天涨粉一万参加新星计划发布优质文章 什么是铁粉如何快速转化粉丝为铁粉多与读者互动鼓励读者也创作高质量的内容 后记 &#x1f3d8;️&#x1f3d8;️个人简介&#xff1a;以山河作礼。 &a…

工作读研两不误?同等学力申硕值不值得读?

根据教育部公布的最新数据&#xff1a; 今年全国考研报考人数达到474万人&#xff0c;相较去年增加17万人。 据中国青年报称据媒体报道&#xff0c; 2023年考研报名人数达到 474万人&#xff0c;而录取率不超过 20%&#xff0c;超过 300万考研学子注定落榜&#xff01; 一名女…

这所广东的211,录取平均分360+,复录比高达2.24!

一、学校及专业介绍 广东工业大学&#xff08;Guangdong University of Technology&#xff09;简称“广工”&#xff0c;位于广东省广州市&#xff0c;是广东省重点建设的省属重点大学、广东省“211工程”、首批广东省高水平大学、广东省高水平理工科大学、国家“111计划”“2…

python:并发编程(三)

前言 本文将和大家一起探讨进程、线程、协程的监控方式&#xff0c;方便我们将这些“虚的东西”具体化&#xff0c;也方便讲解诸如子进程这些概念。我相信&#xff0c;本章将会为后续学习提供非常有用的帮助。本章内容将基于win10系统&#xff0c;为大家展现一个具体化的进程、…

算法修炼之练气篇(Python版)——练气一层初期

✨博主&#xff1a;命运之光 &#x1f984;专栏&#xff1a;算法修炼之练气篇&#xff08;C\C版&#xff09; &#x1f353;专栏&#xff1a;算法修炼之筑基篇&#xff08;C\C版&#xff09; ✨博主的其他文章&#xff1a;点击进入博主的主页​​​​​​ 前言&#xff1a;Pyth…

ChineseBERT使用指北

文章目录 ChineseBert 模型介绍开源代码使用方法未完待续 ChineseBert 模型介绍 论文地址&#xff1a;https://arxiv.org/pdf/2106.16038.pdf 代码地址&#xff1a;https://github.com/ShannonAI/ChineseBert bert是语义模型&#xff0c;因此无法解决形近字、音近字的问题。 …

C语言:写一个函数返回参数二进制中 1 的个数(三种思路)

题目&#xff1a; 链接&#xff1a;二进制中1的个数__牛客网 来源&#xff1a;牛客网 输入一个整数 n &#xff0c;输出该数32位二进制表示中1的个数。其中负数用补码表示。 示例&#xff1a; 输入 10 输出 2 说明 十进制中10的32位二进制表示为0000 0000 0000 0…

从零开始 Spring Boot 40:定时任务

从零开始 Spring Boot 40&#xff1a;定时任务 图源&#xff1a;简书 (jianshu.com) 定时任务是一种很常见的需求&#xff0c;比如我们可能需要应用定期去执行一些清理工作&#xff0c;再比如可能需要定期检查一些外部服务的可用性等。 fixedDelay 要在 Spring 中开启定时任…