第1章 Linux 进程管理概述
基于 Linux 6.12.38 源码分析
1.1 进程与线程的概念
1.1.1 什么是进程
进程(Process)是程序执行的实例,是操作系统进行资源分配和调度的基本单位。在 Linux 内核中,进程具有以下特征:
- 独立的地址空间:每个进程拥有自己独立的虚拟内存空间
- 资源所有权:进程拥有文件描述符、信号处理、内存等资源
- 执行上下文:包含程序计数器、栈、寄存器状态等
- 生命周期:从创建到执行,最终退出的完整过程
1.1.2 什么是线程
线程(Thread)是进程内的执行单元,是 CPU 调度的基本单位:
- 共享地址空间:同一进程内的线程共享虚拟内存
- 轻量级:线程创建和切换开销比进程小
- 并发执行:多线程可在多核 CPU 上并行执行
1.1.3 Linux 中的实现
Linux 使用统一的 task_struct 结构表示进程和线程,通过 clone() 系统调用的标志参数控制共享程度:
这种设计使得 Linux 能够高效地实现多线程,称为”轻量级进程”(LWP,Lightweight Process)。
1.2 进程管理子系统架构
1.2.1 整体架构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| ┌─────────────────────────────────────────────────────────────────┐ │ 进程管理子系统 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │ │ │ 进程描述符 │ │ 进程调度器 │ │ 进程创建/退出 │ │ │ │ task_struct │ │ Scheduler │ │ fork/exec/exit │ │ │ │ │ │ │ │ │ │ │ │ - 状态信息 │ │ - CFS │ │ - copy_process │ │ │ │ - 调度信息 │ │ - RT │ │ - do_exit │ │ │ │ - 资源管理 │ │ - Deadline │ │ - wake_up_new │ │ │ └──────────────┘ └──────────────┘ └─────────────────┘ │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │ │ │ PID 管理 │ │ 等待队列 │ │ 信号处理 │ │ │ │ PID Namespace│ │ wait_queue │ │ signal_frame │ │ │ │ │ │ │ │ │ │ │ │ - pid_alloc │ │ - sleep │ │ - do_signal │ │ │ │ - pid_find │ │ - wakeup │ │ - sigaction │ │ │ └──────────────┘ └──────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘
|
1.2.2 核心组件
进程描述符(task_struct)
- 位于
include/linux/sched.h
- 包含进程的所有信息:状态、优先级、内存、文件等
- 通过 slab 分配器动态管理
调度器(Scheduler)
- 核心调度逻辑:
kernel/sched/core.c
- CFS 调度器:
kernel/sched/fair.c
- 实时调度器:
kernel/sched/rt.c
- Deadline 调度器:
kernel/sched/deadline.c
PID 管理
- PID 分配:
kernel/pid.c
- PID 命名空间:
kernel/pid_namespace.c
- 支持容器场景的 PID 隔离
1.3 关键源码位置
1.3.1 进程核心代码
| 功能 |
目录/文件 |
描述 |
| 进程创建 |
kernel/fork.c |
fork/clone/vfork 实现 |
| 进程退出 |
kernel/exit.c |
do_exit、wait 实现 |
| 程序执行 |
fs/exec.c |
execve 系统调用 |
| PID 管理 |
kernel/pid.c |
PID 分配与查找 |
| 命名空间 |
kernel/pid_namespace.c |
PID 命名空间 |
1.3.2 调度器代码
| 功能 |
目录/文件 |
描述 |
| 核心调度 |
kernel/sched/core.c |
schedule 主函数 |
| CFS |
kernel/sched/fair.c |
完全公平调度器 |
| 实时 |
kernel/sched/rt.c |
FIFO/RR 调度 |
| Deadline |
kernel/sched/deadline.c |
EDF 调度 |
| 负载均衡 |
kernel/sched/topology.c |
CPU 间负载均衡 |
1.3.3 头文件
| 头文件 |
路径 |
描述 |
sched.h |
include/linux/ |
主调度头文件 |
sched/prio.h |
include/linux/ |
优先级定义 |
sched/sched.h |
include/linux/ |
调度器内部结构 |
pid.h |
include/linux/ |
PID 管理 |
1.3.4 体系相关代码
| 架构 |
进程管理 |
调度相关 |
| x86_64 |
arch/x86/kernel/process.c |
arch/x86/kernel/entry_64.S |
| ARM64 |
arch/arm64/kernel/process.c |
arch/arm64/kernel/signal.c |
1.4 相关数据结构概览
1.4.1 进程相关结构
1 2 3 4 5 6 7 8 9
| struct task_struct; struct pid; struct pid_namespace; struct signal_struct; struct sighand_struct; struct fs_struct; struct files_struct; struct mm_struct; struct nsproxy;
|
1.4.2 调度相关结构
1 2 3 4 5 6 7 8 9
| struct rq; struct sched_class; struct sched_entity; struct sched_rt_entity; struct sched_dl_entity; struct cfs_rq; struct rt_rq; struct dl_rq; struct task_group;
|
1.4.3 等待队列
1 2
| struct wait_queue_head; struct wait_queue_entry;
|
1.5 进程生命周期
1.5.1 状态转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| fork() │ ↓ ┌─────────────────────────────────────────┐ │ TASK_NEW │ │ (新创建,尚未运行) │ └──────────────┬──────────────────────────┘ │ wake_up_new_task() ↓ ┌─────────────────────────────────────────┐ │ TASK_RUNNING │ │ (就绪队列中,可被调度执行) │ └───────┬───────────────────────┬─────────┘ │ │ 调度器选择 等待资源 │ │ ↓ ↓ ┌──────────────┐ ┌────────────────────┐ │ 正在运行 │ │ TASK_INTERRUPTIBLE │ │ (使用 CPU) │ │ TASK_UNINTERRUPTIBLE│ └──────┬───────┘ └───────────┬────────┘ │ │ 时间片用完/主动yield │ │ 事件到达/信号 ↓ ↓ ┌──────────────┐ ┌──────────────┐ │ TASK_RUNNING │ │ TASK_RUNNING │ └──────────────┘ └──────────────┘
退出路径: do_exit() │ ↓ ┌──────────────┐ │ EXIT_ZOMBIE │ ←─ wait() 回收 └──────┬───────┘ │ release_task() │ ↓ ┌──────────────┐ │ EXIT_DEAD │ │ (被释放) │ └──────────────┘
|
1.5.2 创建过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| pid = fork();
SYSCALL_DEFINE0(fork) { return _do_fork(SIGCHLD, 0, 0, NULL, NULL, 0); }
long _do_fork(unsigned long clone_flags, ...) { p = copy_process(clone_flags, ...);
wake_up_new_task(p);
return pid; }
|
1.6 调度器概述
1.6.1 调度类层次
Linux 采用模块化的调度器设计,支持多种调度策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| ┌──────────────────────────────────────────────────────────┐ │ 调度器核心 │ │ (kernel/sched/core.c) │ │ │ │ schedule() │ │ pick_next_task() │ │ context_switch() │ └──────────────────────────────────────────────────────────┘ │ ┌────────────────┼────────────────┐ │ │ │ ↓ ↓ ↓ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ dl_sched_ │ │ rt_sched_ │ │ fair_sched_│ │ class │ │ class │ │ class │ │ (Deadline) │ │ (实时) │ │ (CFS) │ └─────────────┘ └─────────────┘ └─────────────┘
|
1.6.2 调度策略
| 策略 |
名称 |
优先级范围 |
用途 |
| SCHED_NORMAL |
普通进程 |
100-139 |
分时任务 |
| SCHED_FIFO |
实时 FIFO |
0-99 |
硬实时 |
| SCHED_RR |
实时轮转 |
0-99 |
软实时 |
| SCHED_DEADLINE |
Deadline |
动态 |
严格实时 |
| SCHED_IDLE |
空闲 |
最低 |
后台任务 |
1.7 与其他子系统的关系
1.7.1 内存管理
1 2 3 4
| struct task_struct { struct mm_struct *mm; struct mm_struct *active_mm; };
|
- 进程创建时复制页表
- 写时复制延迟分配物理内存
- 内存回收时通知进程
1.7.2 文件系统
1 2 3 4
| struct task_struct { struct fs_struct *fs; struct files_struct *files; };
|
- fork 时共享或复制文件表
- exec 时关闭 close-on-exec 标志的文件
- exit 时关闭所有打开的文件
1.7.3 中断与异常
- 时钟中断触发调度
- 系统调用返回时检查抢占标志
- 缺页异常处理进程内存访问
1.7.4 信号处理
1 2 3 4 5
| struct task_struct { struct signal_struct *signal; struct sighand_struct *sighand; sigset_t blocked; };
|
- 信号发送时唤醒睡眠进程
- 信号处理函数在用户空间执行
- 信号掩码影响可中断睡眠
1.8 本章小结
本章介绍了 Linux 进程管理的基本概念:
- 进程与线程:Linux 使用统一的 task_struct 表示,通过 clone 标志控制共享程度
- 子系统架构:包含进程描述符、调度器、PID 管理、等待队列、信号处理等核心组件
- 源码组织:核心代码在 kernel/ 目录,调度器在 kernel/sched/,头文件在 include/linux/
- 数据结构:task_struct 是核心,包含进程的所有信息
- 生命周期:从创建到运行,再到退出的完整过程
- 调度策略:支持普通、实时、Deadline、空闲等多种调度策略
接下来的章节将深入分析每个组件的实现细节。