一.线程是什么
线程 = 一组用于“让 CPU 能从上次停下的地方继续执行”的运行时状态集合。
线程是执行所需状态的载体。
线程本身不执行代码,
Core 执行代码;
线程只是告诉 Core:
“我上次跑到这里了,你接着从这儿跑。”
二.线程是由什么组成的
✅ 1️⃣ 寄存器上下文(Register Context)——最核心
这是线程“能继续跑”的根本。
至少包括:
-
PC / RIP:程序计数器(下一条要执行的指令)
-
SP / RSP:栈指针
-
通用寄存器(保存中间计算结果)
-
标志寄存器(条件码等)
没有寄存器上下文,线程就不知道自己跑到哪了。
📌 上下文切换的本质:
就是保存当前线程的寄存器 + 恢复另一个线程的寄存器。
✅ 2️⃣ 栈(Stack)——执行历史与调用现场
每个线程必须有自己的栈。
栈里通常存着:
-
函数调用链(return address)
-
局部变量
-
保存的寄存器值(callee-saved)
-
异常处理信息等
多线程共享代码、共享堆,
但绝对不能共享栈。
📌 这也是为什么:
-
同一个函数
-
在两个线程里
-
可以同时运行而不互相覆盖局部变量
✅ 3️⃣ 线程控制块(TCB / task_struct)——OS 视角的线程本体
这是内核用来管理线程的数据结构。
里面通常包含:
-
线程 ID
-
当前状态(running / runnable / blocked)
-
调度信息(优先级、时间片)
-
所属进程
-
栈指针、寄存器保存区指针
-
CPU 亲和性信息
-
信号、调度统计信息等
这是调度器“认识线程”的唯一方式。
✅ 4️⃣ 所属进程的资源视图(Shared Context)
线程不拥有完整资源,而是共享进程的:
-
虚拟地址空间
-
堆(heap)
-
全局变量
-
文件描述符
-
信号处理设置(大多)
所以你可以这样理解:
进程 = 资源容器
线程 = 执行容器
把这些拼起来,一张“真实结构图”(文字版)
线程
├── 寄存器上下文(能不能继续执行)
├── 私有栈(执行路径)
├── 线程控制块 TCB(调度与管理)
└── 共享进程资源
├── 地址空间
├── 堆
├── 全局变量
└── 文件描述符
三.线程的作用
- 实现并发执行 在一个进程内开启多个线程,可以让多个任务看似“同时”推进,提高 CPU 利用率,尤其是当一个线程因 I/O 等待而停顿时,其他线程可以继续运行。
- 减少上下文切换成本(相对进程) 因为线程共享进程的地址空间和资源,切换时只需保存/恢复寄存器上下文和栈,不必切换页表等内核结构,所以比进程切换快得多。
- 简化数据共享与通信 同一进程的线程天然共享堆、全局变量、文件描述符等,数据传递无需额外的 IPC 机制(但也需注意同步问题,如竞态条件)。
- 充分利用多核 CPU 内核级线程可由操作系统调度到不同核心并行执行,实现真正的硬件并行,提高吞吐量。
四、进程是什么
进程 = 程序的一次执行实例 + 它拥有的资源集合 + 至少一个执行流(线程)。
从操作系统视角看:
- 进程是资源分配的基本单位(内存、文件、信号处理权等分配给进程)
- 进程是独立地址空间的保护边界(一个进程崩溃通常不会直接影响另一个进程)
- 现代操作系统中,进程至少包含一个线程(Linux 2.x 里甚至用轻量级进程来模拟线程),线程才是 CPU 调度的基本单位。
换句话说: 进程 = 资源 + 状态 + 至少一个执行流(线程) 没有线程的进程只是一个静态的资源壳,无法执行代码。
五、进程的组成
1. 操作系统管理视角:进程控制块(PCB)、程序段、数据段
-
PCB在 Linux 中是
task_struct,相当于“进程的身份证和档案” -
内容包括:
- 进程标识(PID、PPID、TGID)
- 进程状态(运行、睡眠、僵尸等)
- 调度信息(优先级、策略)
- 内存管理指针(
mm_struct) - 文件描述符表(
files_struct) - 信号处理结构
- 资源限制(
rlimit) - 上下文指针(指向寄存器备份、内核栈等)
-
程序段
程序段是进程的一部分,包含了程序的代码,即指令序列。程序段是静态的,存放在磁盘上的可执行文件中。
-
数据段
数据段是进程在运行过程中产生的各种数据,包括程序中定义的变量等。数据段也是静态的,反映了进程在某一时刻的状态。
2. 程序运行内存视角:进程地址空间布局
从高地址到低地址一般包括:
- 内核空间:所有进程共享,只有内核态能访问
- 栈(Stack) :每个线程独有,向下增长,存局部变量、调用链
- 内存映射段:动态库、mmap 文件
- 堆(Heap) :动态分配内存,向上增长
- BSS 段:未初始化的全局/静态变量(加载时清零)
- 数据段(.data) :已初始化的全局/静态变量
- 文本段(.text) :程序代码(只读)
3. 进程的资源集合
- 虚拟地址空间:代码、数据、堆、栈、共享库的映射
- 文件描述符表:打开的文件、socket、管道等
- 信号处理设置:如何响应异步事件
- 工作目录、根目录等文件系统信息
- 线程集合:至少一个主线程,可创建更多线程
六、进程的作用
- 资源隔离与保护 每个进程有独立的虚拟地址空间,一个进程的错误(如空指针解引用)不会影响其他进程,提高了系统的稳定性和安全性。
- 资源管理的基本单位 操作系统以进程为单位分配内存、文件句柄、网络端口等资源,进程间资源互不干扰。
- 提供执行环境 进程为代码执行提供完整的上下文:地址空间、文件、信号处理等,使程序能独立于其他程序运行。
- 支持并发与多任务 多进程可以在宏观上同时运行(在多核 CPU 上可真正并行),实现多任务操作系统的基础。
- 简化错误恢复 一个进程崩溃可以被操作系统回收,不影响整个系统或其他进程的运行(守护进程、服务常采用多进程架构)。
七、线程与进程的关系总结(结构化)
| 维度 | 进程(Process) | 线程(Thread) |
|---|---|---|
| 本质 | 资源 + 至少一个执行流的容器 | 执行流的载体(寄存器+栈+TCB) |
| 资源拥有 | 独立地址空间、文件描述符等 | 共享进程资源 |
| 切换成本 | 高(切换页表、刷新 TLB 等) | 低(仅寄存器、栈) |
| 调度单位 | 现代 OS 中调度的基本单位是线程 | 直接被调度器调度 |
| 隔离性 | 强(一个进程崩溃不影响别的进程) | 弱(线程崩溃可能导致整个进程终止) |
| 通信方式 | IPC(管道、消息队列、共享内存等) | 直接读写共享变量(需同步) |
| 创建开销 | 大(分配资源、建立地址空间) | 小(共享资源,仅分配栈和 TCB) |