Linux复习 / 线程相关----线程概念与控制 QA梳理

news2024/12/23 18:49:35

文章目录

    • 前言
    • Q&A
      • 线程概念
        • Q:线程和进程的区别?(为什么要有线程,从进程的角度说明这个问题)
        • Q:Linux是如何设计线程的?
        • Q:学习了线程后,你能说说进程和线程最大的区别是什么吗?
      • 进程和线程的比较
        • Q:线程使用进程的资源,它们之间的所有资源都是共享的吗?有哪些资源不是共享的?
        • Q:线程的优缺点分别是什么?
      • 线程操作
        • Q:线程终止的三种方式分别是什么?
        • Q:为什么pthread_self()的返回值和LWP不一样?
        • Q:为什么要进行线程分离?
        • Q:为什么要由主线程分离子线程?不能子线程自己分离?

前言

本篇博客梳理关于线程相关的Q&A,包括了线程概念与线程的控制。若读者也在复习这块知识,或者正在学习这块知识,可以通过这些Q&A检测自己的知识掌握情况。此外,思维导图已经更新至我的gitee,Q&A之外的体系梳理还请移步思维导图。

Q&A


线程概念

Q:线程和进程的区别?(为什么要有线程,从进程的角度说明这个问题)

A:Linux用task_struct结构体描述一个进程,可以说进程 = task_struct + 内存中的数据与代码。而task_struct包含了进程页表、进程地址空间等资源,创建一个进程就需要为它分配这些资源。值得思考的是:分配资源本身就需要消耗资源,进程是否能充分利用分配得到的资源?而且由于进程具有独立性,进程间想要共享或发送数据,就要进行进程间通信,但通信的成本过高,会消耗过多资源,降低系统的性能。

若操作系统只有进程,那么进程就是系统的基本执行流。

  • 要执行不同的程序,就要创建新的进程,但是创建进程会带来资源的消耗,这是其一
  • 若一个进程要使用另一个进程的数据,就要进行进程间通信,通信的代价也是额外资源的消耗,这是其二

为解决以上两个问题(最主要的两个),线程被引入,线程作为进程的一部分,和进程共享进程地址空间(资源),同时解决了进程间通信与反复创建进程带来的资源消耗问题。

Q:Linux是如何设计线程的?

A:学习进程时,我们说:进程 = task_struct + 内存中的数据与代码,这个说法默认了task_struct是进程控制块,也就是说task_struct是为了进程而设计的结构。但是事实并不是这样,准确的说task_struct是Linux中的一个执行流。若一个进程下没有线程(或者说唯一的线程就是自己),此时的进程就是一个执行流。若一个进程下有多个线程,此时的进程就不再是执行流,此时的执行流是进程下的线程,进程是多个执行流的集合。

所以task_struct即不是为进程设计的,也不是为线程设计的,它是为执行流这个概念设计的,你也可以极端点,认为Linux下没有进程与线程的概念,Linux只有执行流的概念。提出进程和线程只是为了更好的理解操作系统。

回到问题,你可以认为Linux只有执行流的概念,它对应的结构体为task_struct。但是为了使多个执行流可以同时使用相同的资源而不冲突,Linux肯定是要对线程进行设计的。我们可以通过if else判断fork的返回值,控制父子进程,使两进程分别执行不同的代码块(函数),从而使它们的函数栈分离,体现在进程地址空间上,两进程就是使用了不同的空间。这样的思想也体现在线程的设计中,Linux设计了thread_struct结构体,其中有一组变量维护了寄存器地址,这些寄存器则维护了一个函数栈。所以,每个线程都享有一个独立的函数栈(地址空间),这样就解决了线程间数据冲突的问题。
image.png

总结一下:Linux用thread_struct结构体表示线程结构,该结构体中最重要的是一组寄存器地址,这些寄存器维护了线程的函数栈,使线程享有独立的资源,互不冲突。

Q:学习了线程后,你能说说进程和线程最大的区别是什么吗?

A:两者最大的区别就是:承担的职责不同

  • 进程是系统中资源分配的基本单位,系统分配进程地址空间、页表等结构,消耗了大量资源
  • 线程是系统中调度的基本单位,系统分配资源给进程,线程使用进程的一部分资源,以执行任务

进程和线程的比较

Q:线程使用进程的资源,它们之间的所有资源都是共享的吗?有哪些资源不是共享的?

A:

  • 线程独享的资源
  1. 线程ID:需要用不同的线程ID标识同一进程下的不同线程
  2. 一组寄存器与函数栈:为了防止线程之间发送数据冲突,线程需要维护自己的函数栈
  3. errno:每个线程必须独享errno以便在程序崩溃时更快定位错误
  4. 信号屏蔽字:每个线程可以设置自己想要屏蔽的信号
  5. 调度优先级:可以设置线程的优先级以调整线程的执行顺序
  • 线程与进程共享的数据
  1. 文件描述符表:线程和进程打开的文件,彼此都能看到
  2. 信号的递达方式:线程和进程设置的信号递达方式也会彼此影响
  3. 当前工作路径:进程与使用其资源的线程在同一工作路径下运行
  4. 用户id和组id:进程与使用其资源的线程拥有相同的owner和group

Q:线程的优缺点分别是什么?

A:

  • 优点:
  1. 充分使用进程的资源,尽可能的减少不必要进程的创建,提高系统性能
  2. 线程之间数据共享,比起进程间通信,这是一种更高效的通信方式
  3. 创建线程的代价小于进程,因为系统不要为线程分配页表、进程地址空间这样的资源
  4. 切换线程的代价小于进程,因为系统不需要重新加载页表、进程地址空间,只需要重新加载task_struct结构体以及线程的函数栈
  5. 充分利用多处理器的可并行数量
  6. 在含有慢速IO的进程中,可以创建线程等待慢速IO的结束,使进程可以执行其他任务,不必等待慢速IO的结束
  7. 在密集IO的进程中,可以创建多个线程等待IO的结束,使等待时间重叠,有效提高了程序的运行效率
  • 缺点:
  1. 健壮性较差:线程崩溃退出会导致进程的退出
  2. 调试难度大:多线程程序下的错误难以定位

线程操作

Q:线程终止的三种方式分别是什么?

A:

  1. 直接return,不过返回的对象要强转为(void*)
  2. 调用int pthread_exit(void* retval)退出,该函数的参数是一个类型为void*的变量
  3. 调用int pthread_cancel(pthread_t thread)向指定线程发送cancel信号,该线程的返回值为-1

Q:为什么pthread_self()的返回值和LWP不一样?

A:LWP(light weight process),轻量级进程,使用ps -aL可以查看线程的LWP。而pthread_self()的返回值(线程ID)远远大于LWP,其原因是:

  • Linux没有提供线程的操作接口,或者说这些接口不够简便,需要自己设置于管理线程的属性。我们的线程操作基于第三方库,第三方库帮助我们设置与管理线程的属性

  • 第三方库使用struct thread_info结构体存储线程的信息,而这些结构存储在进程地址空间的共享区,线程ID的值就等于这些结构体的首地址

  • 可以通过程序验证,线程ID的值小于栈区地址,大于堆区地址
    image.png

  • LWP是内核的一个概念,内核用LWP对轻量级进程进行管理

  • 线程ID是地址空间的一个概念,通过线程ID可以找到线程的属性,从而对线程进程管理(这是我们通过线程库对线程的间接管理

Q:为什么要进行线程分离?

A:主线程创建的子线程默认具有joinable属性,若主线程不主动join子线程,会造成资源泄漏与线程句柄的耗尽。线程分离后,主线程不用join子线程,子线程结束,其资源会自动释放。

这个问题也能理解为:为什么要join子线程?两个原因:一个是回收子线程的资源,一个是得到子线程的返回值,前者是必要的,而后者是非必要的。当主线程不再关心子线程的返回信息时,主线程可以主动分离该线程。

Q:为什么要由主线程分离子线程?不能子线程自己分离?

A:这是为了防止一些bug的产生,也是一种编程规范。若子线程调用pthread_detach分离自己,主线程无法确定子线程什么时候被分离,如果主线程在在子线程调用pthread_detach之前调用pthread_join该线程,那么主线程会陷入阻塞,但由于该线程被分离,不会向主线程返回,所以主线程会陷入永久的阻塞,程序因此产生bug。

所以不能让子线程调用pthread_detach分离自己,这会带来一些不确定性。同时我们也要确保主线程不要对将要分离或已经分离的子线程做任何操作。

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

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

相关文章

博客系统(后端编程)

这里还是这四个页面: 博客列表页 博客详情页 登录页 博客编辑页 一、准备工作: 1.引入依赖 引入mysql,servlet,jackson的依赖,并且把之前的前端页面拷贝进去. 2.创建目录 并且把相关代码复制进去. 此时目录就完成了!!! 3.复制前端代码 直接ctrlv我们之前的前端代码到web…

目标检测YOLO系列-YOLOV7运行步骤(推理、训练全过程)

下载源代码:点击下载 进入项目根目录并执行以下命令安装requirements.txt中的相关依赖 pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple官网下载权重yolov7.pt(测试使用)、yolov7-tiny.pt(训练使用…

【C++】哈希表:开散列和闭散列

📝 个人主页 :超人不会飞)📑 本文收录专栏:《C的修行之路》💭 如果本文对您有帮助,不妨点赞、收藏、关注支持博主,我们一起进步,共同成长! 目录前言一、基于哈希表的两个…

Spring MVC请求处理流程分析

Spring MVC请求处理流程分析一 Spring MVC 请求处理流程二 Spring MVC 请求处理流程源码分析2.1架构图解2.2 重要时机点分析2.3核心步骤分析2.3.1 getHandler⽅法剖析2.3.2 getHandlerAdapter⽅法剖析2.3.3 ha.handle⽅法剖析2.3.4 processDispatchResult⽅法剖析三 Spring MVC…

Ruby2D总结

Ruby学习心得 学了几天,Ruby2D这个项目我差不多把教程里面的东西做完了,感觉还好,只要每天一有空的话就去做的话就可以快速做好一个项目,不过还是会有一点虚浮感,但学习也是一个不能拖的事情,所以为了平衡…

【SpringBoot2】SpringBoot运维实用篇

SpringBoot运维实用篇 YW-1.SpringBoot程序的打包与运行 ​ 刚开始做开发学习的小伙伴可能在有一个知识上面有错误的认知,我们天天写程序是在Idea下写的,运行也是在Idea下运行的。 ​ 但是实际开发完成后,我们的项目是不可能运行在自己的电…

Java——树的子结构

题目链接 牛客在线oj题——树的子结构 题目描述 输入两棵二叉树A,B,判断B是不是A的子结构。(我们约定空树不是任意一个树的子结构) 假如给定A为{8,8,7,9,2,#,#,#,#,4,7},B为{8,9,2},2个树的结构如下&am…

【C++】引用(上)【深度全面解析】

🌹作者:云小逸 📝个人主页:云小逸的主页 📝Github:云小逸的Github 🤟motto:要敢于一个人默默的面对自己,强大自己才是核心。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前…

stm32cubemx IAP升级(三)

stm32cubemx IAP升级- UARTDMA实现不定长收发数据 板卡:Nucleo-L412 平台:macbook pro 工具:vscode stm32cubemx stm32cubeProgramer cmake toolchain Stm32CubeMx的配置 选择开启一路串口并配置成DMA,并使能中断,配…

优思学院|质量改进必备技能:克罗斯比的14步骤全面解析

菲利普克罗斯比(Philip Crosby)是一位著名的质量管理专家,被誉为"零缺陷之父"、“现代质量运动之父”。他于1926年出生于美国俄亥俄州,曾在美国空军服役。后来他在ITT公司和马丁-马里埃塔公司等企业担任质量管理师和高级…

【pycharm】pycharm配置svn

目录 1、配置svn地址 2、配置svn按钮 3、配置svn地址 4、checkout项目到PycharmProjects 5、使用 6、打开项目或者checkout项目 7、配置虚拟环境 8、虚拟环境安装库 1、配置svn地址 Seting-version control-subversion 找不到svn.exe 点我博文 2、配置svn按钮 VCS--…

C语言课设项目-51单片机-独立按键与矩阵按键

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹) 目录 一、独立按键 1.按键介绍 2.独立按键原理 3.编写独立按键控制程序 二、矩阵按键 1.矩阵按键的由来 2.…

《暮色心迹》开机大吉,在上虞上演一场蓄谋已久的爱情对弈

4月15日,由秀合影视(浙江) 有限公司、辰耀影业文化传媒(北京)有限公司、浙江中创华视文化发展有限公司出品,浙江诺然文化传媒有限公司、北京幻想纵横网络技术有限公司、浙江知马影视服务有限公司、浙江沐阳…

最落魄的时候,身上带着《毛选》

最落魄的时候,包里只带《毛选》的腕儿 史玉柱:营销大咖,早年创业起伏大 东山再起的腕儿 趣讲大白话:成功是用心血浇灌的 【趣讲信息科技133期】 **************************** 90%的企业是销售驱动型 所以要把品牌和营销的事搞透彻…

Buyflag

拿到题目可以获取到几条关键提示如果你想要买flag你必须是CUIT的学生你必须回答正确的密码查看源码也发现有php源码提示信息要求通过POST方式传参,并利用isset检测是否有password字段is_numeric是检测password字段是否为数字或者数字字符串,如果为数字则…

集合,Collection接口,Iterator(迭代器),List接口和方法,ArrayList底层结构和源码分析

数组的不足 长度开始必须指定,而且一旦指定,不能修改保存的必须为同一类型的元素使用数组进行增加/删除元素的示意代码麻烦SuppressWarnings({"all"})抑制警告集合 可以动态保存任意多个对象,使用比较方便提供了一系列方便的操作对…

【零基础学习】Javascript 快速入门(完整篇)简单、适合初学者

【零基础学习】Javascript 快速入门前言:如何解决错误提示(Error)Uncaught TypeError: Cannot set properties of null (setting innerHTML)Uncaught ReferenceError: displayDate is not defined at HTMLButtonElement.onclick安装Visual St…

剪枝与重参第八课:ACNet、DBB、RepVGG重参

目录ACNet、DBB、RepVGG重参前言1. 并行多分支结构1.1. 并行多分支结构 Demo2. ACNet2.1 ACNet简述2.2 init2.3 forward2.4 swtich to deploy2.5 get_equivalent_kernel_bias2.6 Conv2d与BN的融合(重参)2.7 Conv1x3Conv3x1Conv3x3的融合(重参)2.8 模型导出2.9 完整示例代码总结…

【电路理论】KCL、KVL、线性直流电路各大方法、定理详解

博主简介:努力学习的22级计科生一枚~博主主页: 是瑶瑶子啦所属专栏: 电路理论 目录一、KCL、KVL定律1.1:KCL1.2:KVL1.3:总结二、线性直流电路2.1:电阻网络等效变换2.1.1:电阻等效——三角&星…

【Flink】Flink基础

Flink 官网地址 (官网介绍的非常详细,觉得看英文太慢的直接使用浏览器一键翻译,本文是阅读官方文档后进行的内容梳理笔记) https://nightlies.apache.org/flink/flink-docs-release-1.17/docs/dev/python/overview/ 这 Flink API …