一 Linux--多线程

线程线程的概念线程: 线程是OS能够进行运算调度的基本单位 。线程是一个进程中的一个单一执行流,通俗地说,一个程序里的一个执行路线就叫做线程 。
可以知道的是,一个进程至少有一个执行线程,这个线程就是主执行流 。一个进程的多个执行流是共享进程地址空间内的资源,也就是说进程的资源被合理分配给了每一个执行流 , 这些样就形成了线程执行流 。所以说线程在进程内部运行,本质是在进程地址空间内运行 。需要注意的是 , Linux下没有真正意义上的线程,线程是通过进程来模拟实现的 。这句话如何理解?
Linux系统下,没有专门为线程设计相关的数据结构 。那线程又是如何被创建的呢?我们知道 , 创建一个进程,我们需要为它创建相关的数据结构,如:PCB(task_struct)、mm_sturct、页表和file_struct等 。线程的创建和进程的创建是一样的,线程也是创建一个一个的PCB,因为线程是共享进程地址空间的,所以这些线程都维护同一个进程地址空间 。
这样可以看出一个线程就是一个执行流,每一个线程有一个task_struct的结构体,和进程一样 , 这些task_struct都是由OS进行调度 。可以看出在CPU看来 , 进程和线程是没有区别的,所以说Linux下的线程是通过进程模拟实现的 。

一 Linux--多线程

文章插图
继续思考,CPU如何区分Linux下的线程和进程?
其实CPU不需要考虑这个问题 , 在它眼中,进程和线程是没有区别的 , 都是一个一个的task_struct,CPU只管负责调度即可 。
那如何理解我们之前所学的进程?
我们都知道 , 进程是承担分配系统资源的基本实体,曾经CPU看到的PCB是一个完整的进程,也就是只有一个执行流的进程 。现在看到的PCB不一定是完整的进程,可能是一个进程的执行流总的一个分支,也就是多执行流进程 。所以说,现在CPU眼中,看到的PCB比传统的进程更加轻量化了 。这种有多执行流的进程中的每一个执行流都可以看作是一个轻量级进程 。总结地说,线程是轻量级进程 。总结:
简单点来说,每个线程都有自己的PCB,只不过这些PCB都维护和共享这同一块虚拟空间(进程的虚拟空间 , 也就是进程的PCB),但是线程的PCB更轻量级,操作系统分配资源的时候是以进程那块PCB为分配资源的最小单位,所以给进程分配的资源,属于该进程的线程们都共享,而线程是操作系统调度的最小单位,操作系统不会区分线程和进程,在操作系统眼里都是一个个PCB,CPU调度的时候只负责调用PCB就行了 。
  • 实际上无论是创建进程的fork,还是创建线程的pthread_create,底层实现都是调用一个内核函数clone 。
    • 如果复制对方的地址空间,那么就产生出一个进程
    • 如果共享对方的地址空间,就产生一个线程
    • 可以更简单的理解进程和线程的区别 , 进程的创建就类似于深拷贝 , 线程的创建就类似于浅拷贝 , 更有助于理解
Linux下的进程和线程进程: 承担分配系统资源的实体线程: CPU调度的基本单位注意: 进程之间具有很强的独立性,但是线程之间是会互相影响的
线程共享一部分进程数据,也有自己独有的一部分数据:(每个线程都有属于自己的PCB)
  • 线程ID
  • 一组寄存器(记录上下文信息,任务状态段)
  • 独立的栈空间(用户空间栈)
  • 信号屏蔽字
  • 调度优先级
  • errno(错误码)
  • 处理器现场和栈指针(内核栈)
进程的多个线程共享同一地址空间 , 因此Text Segment、Data Segment都是共享的 。如果定义一个函数,在各线程中都可以调用 , 如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:
  • 文件描述符
  • 每种信号的处理方式
  • 当前工作目录
  • 用户ID和组ID
  • 共享.text(代码段)  .data(数据段) .bss(未初始化数据段).heap(堆)
关系图:
一 Linux--多线程

文章插图
Linux线程控制POSIX线程库