【Hello Linux】线程概念

作者:@小萌新
专栏:@Linux
作者简介:大二学生 希望能和大家一起进步!
本篇博客简介:简单介绍linux中的多线程

线程概念

  • 线程基本概念
    • Linux中的线程
    • 进程线程再理解
    • Linux线程和接口的认识
    • Linux线程与进程区别
      • 线程私有的数据
      • 线程公有的数据
      • 进程和线程的关系

线程基本概念

一般在书上我们会这么介绍一个线程

线程是进程内部的一个执行流 他是进程的一部分 粒度要比进程更加细和轻量化

那么我们应该怎么理解呢? 下面是我的梳理思路

首先线程是进程的一个执行流的对吧 那么一个进程中是不是可能有很多的线程呢? 答案当然是肯定的

那么我们就可以推断 系统中一定存在着大量的线程

既然系统中存在着大量的线程 操作系统作为管理者就要想办法将这些线程管理起来

而根据我们管理的法则:先描述 再组织 操作系统会描述这些线程并且将它们进行组织(默认双链表)

那么操作系统要怎么描述这些线程呢? 答案和进程类似 用一个叫做TCB的结构体来描述

在windows操作系统中 操作系统管理线程就是按照我们上面的逻辑进行的

不过在我们的Linux系统中使用了一种更加巧妙的方法

Linux中的线程

之前在进程部分我们讲过 进程 = 程序 + PCB + mm_struct + 页表和mmu + 物理地址 如下图所示

【Hello Linux】线程概念_第1张图片

Linux在创造线程概念的时候并没有像上面我们所推断的一样创造TCB结构体来管理每一个线程 而是复用了进程的PCB结构体

【Hello Linux】线程概念_第2张图片

这些线程的PCB和进程PCB共享一个进程地址空间 它们每个线程都会分走一点代码和数据

在cpu看来此时的PCB是要小于等于我们之前讲解的PCB概念的

可是cpu不关心这些 它认为一个PCB就是一个执行流 它只管执行就好

这里我们就能得出一个重要的结论

Linux中没有为线程专门设计TCB 而是使用进程PCB模拟线程

这样子设计的优点是什么呢?

最直观的优点 我们不必去设计线程TCB了 这代表着我们节省了大量时间去设计数据结构和算法

与此同时 操作系统也只需要聚焦在线程间的资源分配上就好了

进程线程再理解

我们在博客的开篇就提到过了书上有这么一个概念

线程是进程内部的一个执行流 他是进程的一部分 粒度要比进程更加细和轻量化

我们应该怎么理解上面的这句话

  • 内部: 表示线程在进程的虚拟地址空间中
  • 执行流:CPU在调度的时候只看PCB 所以说PCB中曾经指定的方法和数据CPU都可以直接的调度

那么为什么线程是进程的一部分呢? 要回答这个问题 我们需要再深入了解下进程

进程 = 程序 + PCB + mm_struct + 页表和mmu + 物理地址

【Hello Linux】线程概念_第3张图片

在我们之前的学习过程中 进程默认是只有一个执行流的

而在今天的学习之后 进程是可能会有多个执行流的

我们要明确一点 创建进程的代价是非常大的 这里的代价包括时间+空间

  • 时间: cpu处理并创建PCB进程地址空间等资源的时间
  • 空间:创建的PCB和进程地址空间等占用的空间

所以说在内核视角中 进程是承担分配系统资源的基本实体

而线程只需要创建一个PCB和获取一点进程的资源所以说在内核视角中线程是CPU调度的基本单位 承担进程资源的一部分基本实体

Linux线程和接口的认识

在Linux中线程是用进程模拟实现的 所以说Linux中不会给我们提供线程的操作接口 (这里解释下 其实Linux不是没有能力去提供这些操作接口 而是它想要保持一个相对自由的状态给用户) 而是给我们提供了一个在同一个进程地址空间中创建PCB的方法 分配给资源指定的PCB

但是作为一个用户来说 使用这种方法的学习成本太高了 我们更需要一个完整的线程库

所以说一些应用级的开发工程师就在应用层对于轻量级的Linux接口进行封装成为了我们经常使用的原生线程库

Linux线程与进程区别

我们在创建进程的时候通常会为进程创建一个独立的程序地址空间来保证它的独立性而线程则恰恰相反它们只创建PCB共用一个进程地址空间

但是同样的进程间为了通信或者是其他目的也会选择性的共用一块公共资源而线程为了保证自己能够正确运行也会有一些独立的资源

  • 进程具有独立性 但是一部分资源是可以共享的(管道 ipc等)
  • 线程大部分资源是共享的 但是一部分资源是私有的 (PCB 栈 上下文等)

线程私有的数据

  • 线程ID 这个很好理解 因为我们要使用线程ID来区分每个线程
  • 一组寄存器 这组寄存器用来保存线程的上下文信息
  • 栈 每个线程都有临时的数据需要压栈 如果不区分那数据就全乱了
  • 信号屏蔽字
  • 调度优先级

线程公有的数据

因为多个线程是在同一个进程地址空间中 所以说进程地址空间的代码段和数据段都是共享的

  • 如果定义一个函数 在各线程中都可以调用
  • 如果定义一个全局变量 在各线程中都可以访问到

除此之外 各线程还共享以下进程资源和环境

  • 文件描述符表 (进程打开一个文件后其他线程也能够看到)
  • 每种信号的处理方式(SIG_IGN、SIG_DFL或者自定义的信号处理函数)
  • 当前工作目录(cwd)
  • 用户ID和组ID等等

进程和线程的关系

如果我们把国家比作一个操作系统 那么国家中的每个家庭就是一个进程

每个家庭之间是相互独立的 不可能说今天另外一个家庭的人不经过你的同意就住进你家里

但是家庭与家庭之间也需要通信 可能周末会邀请关系好的邻居上你家客厅做客

家庭中的每个人就可以看作是线程 在这个家里大部分的资源是共享的

但是每个人也有自己的隐私 所以说一部分资源是私有的

你可能感兴趣的:(Linux,linux,运维,服务器)