线程与进程

进程与线程的区别

  1. 进程是资源分配的最小单元。
  2. 线程是执行与调度的最小单元。
  3. 一个进程由一个或多个线程组成。
  4. 进程之间资源相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)以及进程级的资源(如打开文件和信号)。
  5. 进程内的线程在其它进程不可见。

PID 与 TID

  • PID: 进程 ID。
  • TID: 线程 ID。进程 PID 和它的主线程的 TID 总是相同的。
  • TGID: 线程组 leader 的 PID。
  • PGID: 进程组 leader 的 PID。一个进程组包含多个进程。进程组中所有进程都有相同的 PGID。
  • SID: 会话 ID (session ID)。一个会话组包含多个进程组,会话组中所有进程都有相同的 SID。
  • Pthread ID: pthread 库提供的 ID。在同一个进程中是唯一的,不同进程不唯一。
  • TPGID: 控制终端的 PGID。由控制终端修改,用于指示当前前台进程组。
USER VIEW:   <-- PID 43 --> <---------- PID 42 ----------->
                             ┌──────────┐                 
                    Fork     │  pid=42  │  New Thread     
                   ─┌────────│ tgid=42  │───────────┐     
                   ▼         └──────────┘           ▼     
             ┌──────────┐                     ┌──────────┐
             │  pid=43  │                     │  pid=44  │
             │ tgid=43  │                     │ tgid=42  │
             └──────────┘                     └──────────┘
KERNEL VIEW: <-- PID 43 --> <--- PID 42 ---> <-- PID 44 -->

线程

  1. 内核空间:内核线程 (Kernel-Level Thread) 与轻量级进程 (Light Weight Process)
  2. 用户空间:用户线程

进程上下文

「待补充」

进程控制块

进程控制块 (PCB: Process Control Block) 是进程存在的唯一标识。 每个进程有且仅有一个 PCB。

PCB 一般包括:

1.程序ID(PID、进程句柄):它是唯一的,一个进程都必须对应一个PID。PID一般是整形数字 2.特征信息:一般分系统进程、用户进程、或者内核进程等 3.进程状态:运行、就绪、阻塞,表示进程现的运行情况 4.优先级:表示获得CPU控制权的优先级大小 5.通信信息:进程之间的通信关系的反映,由于操作系统会提供通信信道 6.现场保护区:保护阻塞的进程用 7.资源需求、分配控制信息 8.进程实体信息,指明程序路径和名称,进程数据在物理内存还是在交换分区(分页)中 9.其他信息:工作单位,工作区,文件信息等

线程上下文

「待补充」

多线程共享资源

  • 堆:由于堆是在进程空间中开辟出来的,所以它是理所当然地被共享的;
  • 全局变量:它是与具体某一函数无关的,所以也与特定线程无关;因此也是共享的
  • 静态变量:虽然对于局部变量来说,它在代码中是“放”在某一函数中的,但是其存放位置和全局变量一样,存于堆中开辟的.bss和.data段,是共享的
  • 文件等公用资源:这个是共享的,使用这些公共资源的线程必须同步。
  • 地址空间
  • 子进程、闹铃、信号及信号服务程序、记账信息
  • 进程代码段

单线程独享资源

  • 寄存器
  • 程序计数器
  • 状态字
  • 线程优先级
  • 错误返回码

上下文切换

CPU 亲和性 (CPU Affinity)

Linux 内核进程调度器具备软 CPU 亲和性,进程/线程通常不会在处理器之间频繁迁移。 Linux 内核也提供系统调用,强行将进程/线程绑定到指定的 CPU 核运行。

绑定到指定的 CPU 核有利于:

  1. 提高 CPU Cache 命中率。
  2. 进程需要高密度的计算,不希望被频繁调度

还可以用 taskset 命令查询或者设置指定进程的亲和性掩码。