【Linux 进程详解】从 PCB 到 fork,一篇搞懂进程核心知识
作为操作系统的核心概念之一,进程 是程序运行的载体,也是理解 Linux 系统调度、资源管理的基础。本文将从进程定义、PCB 结构、进程与程序的区别,到虚拟内存、进程状态、调度机制,再到fork创建子进程的实操,全面梳理进程的核心知识。
一、进程是什么?
进程是程序的一次运行过程,它会占用系统的 CPU、内存等资源。
而操作系统用于管理进程的核心数据结构是 PCB(Process Control Block,进程控制块)------ 每个运行中的进程都对应一个 PCB,存储着进程的关键信息(如 PID、状态、资源限制等)。
二、PCB 的核心内容
PCB 是进程的 "身份证 + 资源清单",以 Linux 系统为例,其 PCB 包含的关键信息(部分):
- PID:进程的唯一标识符;
- 运行状态:如就绪、运行、阻塞等;
- 资源限制:打开文件数上限(默认 1024)、栈大小(默认 8M)等;
- 文件描述符表:记录进程打开的文件、设备等;
- 用户 / 组 ID:进程所属的用户、组权限标识。
三、进程与程序的区别
很多人会混淆 "进程" 和 "程序",核心差异如下:
| 维度 | 程序 | 进程 |
|---|---|---|
| 存在形式 | 永久(存储在磁盘的二进制文件) | 临时(运行时才存在,结束后销毁) |
| 状态变化 | 无(静态文件) | 有(就绪、运行、阻塞等状态切换) |
| 资源占用 | 不占用系统资源 | 占用 CPU、内存等资源 |
| 与其他实体的关系 | 无 | 进程间会竞争系统资源 |
| 运行方式 | 一个程序可运行多次,生成多个进程 | 一个进程对应一个程序的一次运行 |
四、进程的虚拟内存
Linux 中,进程的内存空间是虚拟地址空间 ,通过地址映射表与物理内存关联。这样做的核心目的是:
- 隔离性:进程不能直接访问其他进程的内存,避免相互干扰;
- 安全性:通过权限控制(如内核空间 / 用户空间划分),防止进程非法访问系统资源。
进程的虚拟地址空间通常分为多个段:
- Code 段:存储程序的代码指令;
- Data 段:存储全局变量、静态变量;
- Heap 段 :动态内存分配区域(如
malloc申请的内存); - Stack 段:存储函数栈帧、局部变量(默认大小 8M);
- 共享区:用于进程间共享数据(如共享内存)。
五、进程的分类
根据运行特性,进程可分为 3 类:
- 交互式进程:需要用户输入、输出的进程(如 Shell、文本编辑器);
- 批处理进程:后台自动运行的进程(如定时任务);
- 守护进程 :长期运行的后台进程(如
sshd、nginx),通常在系统启动时运行,等待特定事件触发。
六、进程的状态与切换
进程在生命周期中会在多个状态间切换,Linux 中典型的进程状态包括:
- 就绪态:进程已准备好,等待 CPU 调度;
- 运行态:进程正在 CPU 上执行;
- 阻塞态:进程等待某事件(如 IO 完成、信号),暂时无法运行。
状态切换的触发条件:
- 就绪态 → 运行态:CPU 调度该进程;
- 运行态 → 就绪态:时间片耗尽,或被更高优先级进程抢占;
- 运行态 → 阻塞态:进程发起 IO 请求、等待信号等;
- 阻塞态 → 就绪态:等待的事件完成(如 IO 结束)。
七、进程的调度
Linux 是多任务操作系统,但 CPU 核心数有限,因此需要进程调度来决定 "下一刻哪个进程运行"。
常见的调度算法:
- 时间片轮转:每个进程分配固定时间片,超时则切换;
- 短任务优先:优先调度运行时间短的进程;
- 进程优先级:为进程设置优先级,高优先级进程优先运行;
- 完全公平调度(CFS):Linux 默认调度算法,以 "公平分配 CPU 时间" 为核心。
八、进程的创建:fork 函数
在 Linux 中,创建新进程的核心函数是fork(),它会复制当前进程(父进程)的 PCB、地址空间等资源,生成一个新进程(子进程)。
fork 的返回值规则
- 父进程中:返回子进程的 PID(大于 0);
- 子进程中:返回 0;
- 创建失败:返回 - 1。
示例:fork 创建子进程
c
运行
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid > 0) {
// 父进程逻辑
printf("父进程PID:%d,子进程PID:%d\n", getpid(), pid);
} else if (pid == 0) {
// 子进程逻辑
printf("子进程PID:%d,父进程PID:%d\n", getpid(), getppid());
} else {
perror("fork失败");
return 1;
}
return 0;
}
运行结果(示例):
plaintext
父进程PID:1234,子进程PID:1235
子进程PID:1235,父进程PID:1234
九、进程相关的常用命令
- ps :查看进程信息(如
ps aux查看所有进程); - top:实时监控进程的 CPU、内存占用;
- kill :向进程发送信号(如
kill -9 PID强制终止进程)。
以上就是 Linux 进程的核心知识,从概念到实操覆盖了进程的生命周期、管理、调度等关键环节。