# Linux 进程管理概述 - 进程理论与系统基础

URL: https://caijiao.org/linux/process/overview
Source: docs/linux/process/overview.md
Description: 全面介绍 Linux 进程管理的基本概念、进程状态、调度机制、内存管理和进程间通信等核心内容，帮助理解 Linux 系统如何管理和控制运行中的程序。

## 1. 进程基础概念

### 1.1 什么是进程

在 Linux 系统中，进程（Process）是程序在执行时的一个实例。当用户运行一个程序时，操作系统会加载程序到内存，并创建一个进程来管理该程序的执行。每个进程都有自己独立的地址空间、资源和状态。

### 1.2 进程与程序的区别

- **程序**：是存储在磁盘上的可执行文件，是静态的代码和数据
- **进程**：是程序执行的实例，是动态的，有生命周期和状态变化
- 一个程序可以同时被多个用户运行，生成多个进程

### 1.3 进程 ID (PID)

每个进程在创建时都会被分配一个唯一的进程标识符（Process ID，PID）。PID 是一个非负整数，用于在系统中唯一标识一个进程。

- `init` 或 `systemd` 进程是系统启动的第一个进程，PID 为 1
- 内核线程的 PID 通常为负数
- 当进程终止后，其 PID 可以被重新分配给新进程（但有延迟机制避免混淆）

### 1.4 进程类型

在 Linux 系统中，进程可以分为以下几种类型：

- **用户进程**：由用户启动的普通进程
- **系统进程**：由操作系统创建和管理的进程
- **守护进程**：在后台运行，不与任何控制终端关联的进程
- **内核线程**：直接在操作系统内核中运行的特殊进程

### 1.5 进程状态

Linux 进程具有多种状态，反映了进程当前的运行情况：

- **R (Running)**：进程正在运行或在就绪队列中等待运行
- **S (Sleeping)**：进程处于可中断睡眠状态，等待某个事件发生
- **D (Disk Sleep)**：进程处于不可中断睡眠状态，通常在进行 I/O 操作
- **T (Stopped)**：进程被暂停，可以通过信号恢复运行
- **Z (Zombie)**：进程已终止，但父进程尚未回收其资源
- **X (Dead)**：进程已死亡，这是一个瞬时状态，通常看不到
- **I (Idle)**：内核线程的空闲状态

## 2. 进程的生命周期

### 2.1 进程的创建

在 Linux 系统中，进程主要通过以下方式创建：

- **fork()**：创建一个与父进程几乎相同的新进程
- **vfork()**：与 fork() 类似，但有更多限制，主要用于创建子进程后立即调用 exec()
- **clone()**：创建线程或具有特定共享资源的进程
- **exec()**：用新程序替换当前进程的代码和数据，但保留进程 ID 和其他属性

### 2.2 进程树

Linux 系统中的进程形成一个树形结构，其中：

- **父进程**：创建其他进程的进程
- **子进程**：被其他进程创建的进程
- **祖先进程**：所有上级进程
- **子后代进程**：所有下级进程

每个进程（除了初始进程）都有一个父进程，可以有多个子进程。

### 2.3 进程终止

进程终止的主要方式有：

- **正常终止**：
  - 程序执行完成并返回退出状态
  - 调用 exit() 或 _exit() 函数
  - 主函数 return 语句
- **异常终止**：
  - 接收到终止信号（如 SIGTERM、SIGKILL）
  - 执行非法操作（如访问无效内存）导致信号（如 SIGSEGV）
  - 严重错误（如除以零）

### 2.4 僵尸进程与孤儿进程

- **僵尸进程**：进程已终止，但父进程尚未调用 wait() 或 waitpid() 回收其资源，系统中仍保留其进程表项
- **孤儿进程**：父进程先于子进程终止的进程，这些进程会被 init/systemd 进程（PID 1）接管

## 3. 进程调度

### 3.1 调度器概述

Linux 调度器负责决定哪个进程能够获得 CPU 时间，它是操作系统核心功能之一。现代 Linux 使用完全公平调度器（Completely Fair Scheduler，CFS）作为默认调度器。

### 3.2 调度策略

Linux 支持多种调度策略：

- **SCHED_NORMAL (SCHED_OTHER)**：默认的分时调度策略，用于普通进程
- **SCHED_FIFO**：先进先出实时调度策略，优先级高的进程一直运行直到阻塞或主动让出 CPU
- **SCHED_RR**：轮询实时调度策略，类似于 FIFO，但添加了时间片限制
- **SCHED_BATCH**：批处理调度策略，适合计算密集型、不需要交互式响应的进程
- **SCHED_IDLE**：空闲调度策略，优先级最低，只有在系统空闲时才会运行
- **SCHED_DEADLINE**：基于截止时间的调度策略，适合实时任务

### 3.3 优先级机制

Linux 使用两种优先级概念：

- **nice 值**：范围从 -20 到 19，值越小优先级越高
- **实时优先级**：范围从 0 到 99，值越大优先级越高

普通进程使用 nice 值，实时进程使用实时优先级。

### 3.4 进程优先级调整

可以通过以下方式调整进程优先级：

- **nice** 命令：启动具有特定 nice 值的进程
- **renice** 命令：调整正在运行进程的 nice 值
- **chrt** 命令：设置或获取实时进程的调度策略和优先级

## 4. 内存管理

### 4.1 进程地址空间

每个 Linux 进程都有自己独立的虚拟地址空间，通常分为以下几个部分：

- **文本段（Text Segment）**：存储可执行代码
- **数据段（Data Segment）**：存储初始化的全局变量和静态变量
- **BSS 段（Block Started by Symbol）**：存储未初始化的全局变量和静态变量
- **堆（Heap）**：动态内存分配区域
- **栈（Stack）**：存储局部变量、函数调用信息

### 4.2 内存分配

Linux 进程内存分配主要通过以下机制：

- **malloc/free**：C 语言标准库函数，管理用户空间的内存分配
- **brk/sbrk**：系统调用，调整进程数据段的大小
- **mmap**：内存映射系统调用，可以将文件或设备映射到进程地址空间

### 4.3 内存使用统计

Linux 提供了多种工具来监控进程的内存使用情况：

- **/proc/PID/status**：包含进程的内存使用统计信息
- **/proc/PID/statm**：包含进程的内存使用详细统计
- **top, htop**：交互式进程监控工具，显示内存使用情况
- **ps aux**：显示进程的内存使用率

## 5. 进程间通信

### 5.1 进程间通信概述

Linux 提供了多种进程间通信（IPC）机制，使不同进程能够交换数据和同步操作。

### 5.2 管道（Pipes）

管道是最简单的 IPC 机制之一，分为：

- **匿名管道**：通过 pipe() 系统调用创建，只能用于有亲缘关系的进程间通信
- **命名管道（FIFO）**：通过 mkfifo() 或 mknod() 创建，允许无亲缘关系的进程间通信

### 5.3 信号（Signals）

信号是异步通知机制，用于通知进程发生了特定事件：

- **常用信号**：SIGTERM（优雅终止）、SIGKILL（强制终止）、SIGINT（中断信号）
- **信号处理**：进程可以捕获、忽略或默认处理信号

### 5.4 消息队列（Message Queues）

消息队列允许进程以消息的形式交换数据，具有以下特点：

- 消息有类型和优先级
- 消息可以在进程间传递，即使发送进程已终止
- 有一定的系统资源限制

### 5.5 共享内存（Shared Memory）

共享内存是最快的 IPC 机制，通过以下步骤使用：

1. 使用 shmget() 创建共享内存段
2. 使用 shmat() 将共享内存附加到进程地址空间
3. 进程间直接读写共享内存
4. 使用 shmdt() 分离共享内存
5. 使用 shmctl() 控制或删除共享内存

### 5.6 信号量（Semaphores）

信号量是用于同步和互斥的计数器，主要用于控制对共享资源的访问：

- **二元信号量**：值只能是 0 或 1，用于互斥访问
- **计数信号量**：值可以是任意非负整数，用于控制资源的并发访问数量

### 5.7 套接字（Sockets）

套接字不仅可以用于网络通信，也可以用于本地进程间通信（Unix 域套接字）：

- **Unix 域套接字**：使用文件系统路径作为地址
- **网络套接字**：使用 IP 地址和端口号作为地址

## 6. 进程控制

### 6.1 进程创建与执行

- **fork()**：创建子进程
- **exec() 系列函数**：执行新程序
- **system()**：在新进程中执行 shell 命令
- **popen()**：创建管道连接到命令的标准输入或输出

### 6.2 进程终止与等待

- **exit()/exit()**：终止进程
- **wait()/waitpid()**：等待子进程终止并获取退出状态
- **kill()**：向指定进程发送信号

### 6.3 进程组与会话

- **进程组**：一组相关进程的集合，有一个唯一的进程组 ID (PGID)
- **会话**：一组相关进程组的集合，有一个会话 ID (SID)
- **会话首进程**：创建会话的进程
- **控制终端**：与会话关联的终端

## 7. 守护进程

### 7.1 守护进程概述

守护进程是在后台运行且不与任何控制终端关联的特殊进程，通常以 d 结尾（如 sshd、httpd）。

### 7.2 创建守护进程的步骤

标准的守护进程创建过程（也称为 daemonization）包括以下步骤：

1. 调用 fork() 创建子进程，然后父进程退出
2. 子进程调用 setsid() 创建新会话，摆脱控制终端
3. 再次调用 fork()，确保守护进程不是会话首进程，避免重新获取控制终端
4. 修改工作目录（通常为 /）
5. 设置文件权限掩码
6. 关闭所有不需要的文件描述符
7. 重新定向标准输入、输出和错误到 /dev/null

### 7.3 系统守护进程

Linux 系统中有许多重要的守护进程：

- **init/systemd**：系统初始化进程，管理系统启动和运行
- **sshd**：SSH 服务器守护进程，提供安全远程登录
- **cron**：定期执行任务的守护进程
- **syslogd/rsyslogd**：系统日志守护进程
- **httpd/nginx**：Web 服务器守护进程

## 8. 进程监控与管理工具

### 8.1 进程状态查看

- **ps**：显示当前进程状态
- **top**：动态显示进程状态和系统资源使用情况
- **htop**：top 的增强版，提供更友好的界面
- **pstree**：以树形结构显示进程关系

### 8.2 进程控制命令

- **kill**：向进程发送信号
- **nice/renice**：调整进程优先级
- **bg/fg**：管理后台和前台作业
- **jobs**：显示当前 shell 的作业列表

### 8.3 系统资源监控

- **vmstat**：显示虚拟内存统计信息
- **iostat**：显示 CPU 和 I/O 统计信息
- **netstat/ss**：显示网络连接、路由表等网络统计信息
- **free**：显示内存使用情况
- **mpstat**：显示处理器相关统计信息

## 9. 总结

Linux 进程管理是操作系统的核心功能之一，涉及进程的创建、执行、调度、通信和终止等多个方面。通过本文的学习，您应该对 Linux 进程的基本概念、生命周期、调度机制、内存管理和进程间通信有了全面的了解。

掌握 Linux 进程管理的理论知识对于系统管理员、开发人员和安全专家来说都非常重要。它不仅有助于理解系统的工作原理，也为使用各种进程管理工具和编写高效程序提供了理论基础。

在后续的章节中，我们将详细介绍各种进程管理命令的使用方法和最佳实践，帮助您更好地管理和优化 Linux 系统中的进程。
