【Linux】初识线程

在这里插入图片描述

👦个人主页:Weraphael
✍🏻作者简介:目前正在学习c++和算法
✈️专栏:Linux
🐋 希望大家多多支持,咱一起进步!😁
如果文章有啥瑕疵,希望大佬指点一二
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注😍


前言

在很多教科书上是这么定义线程的:

  • 线程是进程的一个执行分支。
  • 线程执行粒度比进程更细。
  • 线程就是进程内部的一个执行流。

当初学者看到以上定义,我想他/她的内心是非常崩溃的。那么这篇博客将由浅入深带领大家了解进程的概念等相关知识。

请添加图片描述

一、 如何理解Linux中的线程

理解线程之前需要先简单回顾一下进程。

程序运行后,该程序的相关代码和数据会被加载到内存中,然后操作系统为其创建对应的数据结构如进程控制块task_struct,由于进程具有独立性,操作系统还会为进程创建进程地址空间mm_struct,并通过页表 + MMU机制建立虚拟地址和物理地址之间的映射关系。

在这里插入图片描述

如上,进程要访问代码和数据,必须通过其进程地址空间和页表来完成。换句话说,进程所能看到的资源是通过地址空间来确定的。因此,地址空间可以被视为进程的资源窗口

在这里插入图片描述

由于进程具有独立性,即使是父子进程,操作系统也会为子进程创建独立的进程控制块,并复制父进程的地址空间的映射关系,以实现父子资源共享。需要注意的是,如果子进程尝试修改父进程的共享资源,如代码段,操作系统会启动写时拷贝机制,为修改的值分配新的物理内存空间,并更新页表的映射关系。

总之,当创建进程时,进程控制块、虚拟地址空间和页表映射等是必不可少的组成部分。所以创建一个进程的成本非常高。

在这里插入图片描述

为了避免这种繁琐的操作,引入了线程的概念。之前我们一直认为,一个task_struct对应一个进程地址空间,但其实一个进程地址空间可以对应很多个task_struct。因此所谓线程其实就是:仅需创建task_struct,而无需为其单独创建进程地址空间和页表等。相反,该task_struct可以与已有进程共享其进程地址空间,即线程共享进程的资源窗口,即线程本质在进程的地址空间内运行

那么现在就可以理解【前言】中线程相关的概念:

  • 线程的执行粒度比主进程更细。什么是更细呢?进程是整个程序的一次执行过程,而线程通常只执行进程代码的一部分。所以,线程可以看作是整个进程的执行分支

  • 执行代码(任务)时,我们将其称为执行流。将进程资源合理分配给每个执行流,就形成了线程执行流。并且任何执行流执行都要有资源,即线程要在进程的地址空间内运行

  • 线程的调度成本更低。无论是线程还是进程的上下文切换,都涉及将值加载到CPU的寄存器中,以便新的执行体可以继续执行。这一步骤包括将程序计数器PC等寄存器的值设置为新线程或进程上次中断的位置,以便程序可以继续执行。

    • 如果切换的是进程而非线程,操作系统可能还需要切换页表,以确保新进程可以访问正确的地址空间,又或者是更新文件描述符表等进程相关的资源状态等。

    • 而对于线程来说,因为线程共享同一进程的地址空间和大部分资源(如打开的文件等),因此在切换时不需要切换这些资源,只需要切换线程的私有状态即可。

说明:上下文切换是一项开销较大的操作,因为它涉及到保存和恢复大量的状态信息,并且可能涉及到内核态和用户态之间的切换。

【感性理解】
家庭(进程)作为一个整体,有着共同的目标:将家里的日子过好(执行整个程序)。为了实现这个目标,家庭成员(线程)需要各自执行不同的任务。 在家庭中,虽然每个人有自己的任务,但大家都在同一个家庭环境中工作(线程在进程内部运行),家里的房子、车子、家庭预算等是共享的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值