作者:@小萌新
专栏:@Linux
作者简介:大二学生 希望能和大家一起进步!
本篇博客简介:简单介绍linux中的多线程
一般在书上我们会这么介绍一个线程
线程是进程内部的一个执行流 他是进程的一部分 粒度要比进程更加细和轻量化
那么我们应该怎么理解呢? 下面是我的梳理思路
首先线程是进程的一个执行流的对吧 那么一个进程中是不是可能有很多的线程呢? 答案当然是肯定的
那么我们就可以推断 系统中一定存在着大量的线程
既然系统中存在着大量的线程 操作系统作为管理者就要想办法将这些线程管理起来
而根据我们管理的法则:先描述 再组织 操作系统会描述这些线程并且将它们进行组织(默认双链表)
那么操作系统要怎么描述这些线程呢? 答案和进程类似 用一个叫做TCB的结构体来描述
在windows操作系统中 操作系统管理线程就是按照我们上面的逻辑进行的
不过在我们的Linux系统中使用了一种更加巧妙的方法
之前在进程部分我们讲过 进程 = 程序 + PCB + mm_struct + 页表和mmu + 物理地址 如下图所示
Linux在创造线程概念的时候并没有像上面我们所推断的一样创造TCB结构体来管理每一个线程 而是复用了进程的PCB结构体
这些线程的PCB和进程PCB共享一个进程地址空间 它们每个线程都会分走一点代码和数据
在cpu看来此时的PCB是要小于等于我们之前讲解的PCB概念的
可是cpu不关心这些 它认为一个PCB就是一个执行流 它只管执行就好
这里我们就能得出一个重要的结论
Linux中没有为线程专门设计TCB 而是使用进程PCB模拟线程
这样子设计的优点是什么呢?
最直观的优点 我们不必去设计线程TCB了 这代表着我们节省了大量时间去设计数据结构和算法
与此同时 操作系统也只需要聚焦在线程间的资源分配上就好了
我们在博客的开篇就提到过了书上有这么一个概念
线程是进程内部的一个执行流 他是进程的一部分 粒度要比进程更加细和轻量化
我们应该怎么理解上面的这句话
那么为什么线程是进程的一部分呢? 要回答这个问题 我们需要再深入了解下进程
进程 = 程序 + PCB + mm_struct + 页表和mmu + 物理地址
在我们之前的学习过程中 进程默认是只有一个执行流的
而在今天的学习之后 进程是可能会有多个执行流的
我们要明确一点 创建进程的代价是非常大的 这里的代价包括时间+空间
所以说在内核视角中 进程是承担分配系统资源的基本实体
而线程只需要创建一个PCB和获取一点进程的资源所以说在内核视角中线程是CPU调度的基本单位 承担进程资源的一部分基本实体
在Linux中线程是用进程模拟实现的 所以说Linux中不会给我们提供线程的操作接口 (这里解释下 其实Linux不是没有能力去提供这些操作接口 而是它想要保持一个相对自由的状态给用户) 而是给我们提供了一个在同一个进程地址空间中创建PCB的方法 分配给资源指定的PCB
但是作为一个用户来说 使用这种方法的学习成本太高了 我们更需要一个完整的线程库
所以说一些应用级的开发工程师就在应用层对于轻量级的Linux接口进行封装成为了我们经常使用的原生线程库
我们在创建进程的时候通常会为进程创建一个独立的程序地址空间来保证它的独立性而线程则恰恰相反它们只创建PCB共用一个进程地址空间
但是同样的进程间为了通信或者是其他目的也会选择性的共用一块公共资源而线程为了保证自己能够正确运行也会有一些独立的资源
因为多个线程是在同一个进程地址空间中 所以说进程地址空间的代码段和数据段都是共享的
除此之外 各线程还共享以下进程资源和环境
如果我们把国家比作一个操作系统 那么国家中的每个家庭就是一个进程
每个家庭之间是相互独立的 不可能说今天另外一个家庭的人不经过你的同意就住进你家里
但是家庭与家庭之间也需要通信 可能周末会邀请关系好的邻居上你家客厅做客
家庭中的每个人就可以看作是线程 在这个家里大部分的资源是共享的
但是每个人也有自己的隐私 所以说一部分资源是私有的