Linux 进程管理详解:从概念到实战

本篇为 Linux 系统开发学习笔记,梳理进程核心概念、实操命令、虚拟地址空间、进程创建、调度机制与 C 语言 API 实战,适合 C/C++ 后端、Linux 开发人员阅读。

1. 进程基础概念

1.1 程序与进程

  • 程序 :存储在磁盘外存上的代码文件,属于静态的指令集合。
  • 进程:程序运行起来的动态实例,包含创建、调度、销毁完整生命周期。

一个程序可以对应多个进程,例如服务程序支持多用户访问,会同时启动多个进程实例。

1.2 进程常用操作命令

表格

命令 功能说明
top 实时监控系统进程,默认按 CPU 使用率排序
ps -ef 输出全部进程信息,非实时刷新
`ps -ef grep *.out` 过滤查找指定进程
pstree 树形展示进程父子继承关系
ps -aux 查看进程 CPU、内存、完整运行状态
kill 向进程发送信号,用于终止任务
kill -l 查看全部 kill 信号列表
kill -信号编号 PID 给指定进程发送对应信号

关键字段解析

  • PID:进程唯一标识符,区分进程,不是进程名称
  • PPID:父进程 ID,代表当前进程由哪个进程创建
  • USER:启动该进程的操作系统用户

1.3 常用信号

  1. SIGSEGV(编号 11)段错误 程序访问非法内存地址,直接崩溃,报错:Segmentation Fault
  2. SIGKILL(编号 9)强制终止 立刻强制杀掉进程;无法捕获、阻塞、忽略,属于最高权限信号。

✨实操建议:优先使用kill PID(默认 15 号 SIGTERM,优雅退出);进程卡死无响应时,再使用kill -9 PID强制杀死。

1.4 前后台任务管理

表格

命令 作用
./a.out & 将程序放到后台运行
jobs 查看当前终端后台任务列表
fg 任务编号 把后台任务切回前台执行

1.5 进程优先级 NI

Linux 规则:NI 数值越小,优先级越高,和 Windows 规则相反。 进程默认 NI 值为 10。

表格

命令 作用
nice -n 10 ./a.out 启动程序时指定优先级
renice -n 优先级 PID 修改正在运行进程的优先级

2. 进程创建

2.1 虚拟地址空间

  • 32 位系统:虚拟地址总空间 4GB
  • 64 位系统:理论上限2^64=16EB,内核实际使用 48 位地址,可用最大 256TB

虚拟地址空间分段

表格

说明
.text文本段 机器指令代码,只读属性
.data已初始化数据段 已经赋值的全局变量
.bss未初始化数据段 未初始化全局变量,程序加载后自动清零
.rodata常量区 字符串常量,只读
Heap 堆 向上增长,malloc动态申请内存
Stack 栈 向下增长,存放局部变量、函数调用栈帧
内核空间 用户态程序无权访问,归属操作系统内核

核心要点:

  1. 每个进程拥有独立虚拟地址空间;
  2. MMU 内存管理单元完成虚拟地址到物理地址映射;
  3. 不同进程即便虚拟地址相同,映射到的物理内存也互不干扰。
复制代码
┌─────────────────────────────┐ 高地址 (0xFFFFFFFF)
│        内核空间             │ ← 用户态无法访问
│    (Kernel Space)           │   只读
├─────────────────────────────┤
│        栈 (Stack)           │ ← 向下增长
│         ↓                   │   局部变量、函数调用
├─────────────────────────────┤
│         空洞(未使用)        │
├─────────────────────────────┤
│         堆 (Heap)           │ ← 向上增长
│         ↑                   │   malloc分配
├─────────────────────────────┤
│    字符串常量区(.rodata)     │ ← 字符串常量
├─────────────────────────────┤
│   未初始化数据段(.bss)      │ ← 未初始化全局变量
├─────────────────────────────┤
│   已初始化数据段(.data)     │ ← 初始化全局变量
├─────────────────────────────┤
│       代码段(.text)         │ ← 程序代码(只读)
└─────────────────────────────┘ 低地址 (0x00000000)

3. 进程调度

3.1 调度算法演变

  1. 先来先服务 FCFS:按照任务到达顺序依次执行
  2. 短作业优先 SJF:耗时短的任务优先调度
  3. 高优先级调度:优先级高的任务优先运行
  4. 时间片轮转(Linux 当前核心调度)

执行流程:中断当前进程 → 保存上下文现场 → 切换进程 → 恢复现场继续运行 宏观上多个程序同时运行,微观 CPU 同一时刻只能执行一个进程。

  1. 多级反馈队列、负载均衡:现代 Linux 调度器优化方向

3.2 进程状态

表格

状态标识 状态名称 含义
R 就绪 / 运行态 就绪:等待 CPU 调度;运行:正在 CPU 执行
S 可唤醒等待态 等待 IO 或资源,收到信号可被唤醒
D 不可唤醒等待态 深度阻塞,信号无法打断,常见磁盘 IO 等待
T 停止态 进程被暂停,例如 gdb 调试场景
Z 僵尸态 进程执行完毕,但父进程没有回收资源,残留僵尸进程
X 结束态 进程全部资源回收,彻底销毁

⚠️注意:僵尸进程 Z,子进程结束父进程未调用 wait 回收产生,开发中需要尽量规避。

4. 进程系统调用接口

4.1 fork () 函数

复制代码
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);

功能:创建子进程,调用 fork 的进程为父进程。

  • 子进程会复制父进程全部内容:代码、数据、堆栈、文件描述符;
  • fork 返回之后,父子进程相互独立运行。

返回值

  • 成功:父进程返回子进程 PID ;子进程返回0
  • 失败:返回 -1

4.2 fork 示例代码

复制代码
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    pid_t pid = fork();
    if (pid == -1) {
        perror("fork failed");
        return 1;
    }

    if (pid == 0) {
        // 子进程逻辑
        printf("子进程: PID = %d, 父进程 PID = %d\n",
                getpid(), getppid());
    } else {
        // 父进程逻辑
        printf("父进程: PID = %d, 子进程 PID = %d\n",
                getpid(), pid);
    }
    return 0;
}

运行输出示例:

复制代码
父进程: PID = 1234, 子进程 PID = 1235
子进程: PID = 1235, 父进程 PID = 1234

4.3 写时复制 COW (Copy‑on‑Write)

fork 不会直接拷贝全部物理内存,是 Linux 重要优化机制。

  1. fork 创建子进程,父子进程共享同一物理内存页,页面标记为只读;
  2. 父或子进程尝试修改内存,触发缺页异常;
  3. 内核复制一份全新物理页给写入进程,更新页表映射,完成内存隔离。

关键点:fork 刚完成,父子共享物理内存;只有发生写操作,才会复制内存,大幅提升 fork 执行效率。

简易逻辑流程:

复制代码
父进程调用fork()
    ↓
创建子进程虚拟地址空间
    ↓
父子共享父进程物理内存(只读权限)
    ↓
是否有进程执行写操作?
├─否 → 继续共享物理页
└─是 → 触发COW,复制独立物理页,父子内存隔离

5. 总结

  1. 进程是程序动态运行实例,拥有独立虚拟地址空间;
  2. Linux 依靠时间片轮转调度,实现宏观并行、微观串行;
  3. fork()创建子进程,借助写时复制 COW 兼顾性能与内存隔离;
  4. 日常运维熟练使用pstopkilljobs等命令;
  5. 开发中要重点防范僵尸进程、D 状态阻塞进程这类异常。
相关推荐
JJJennie77716 小时前
MAI Gateway技术揭秘:大模型网关能做什么?从原理到落地
linux·服务器·网络·ai网关
YangYang9YangYan17 小时前
2026 校招审计风控岗位 JD 拆解,工具、专业能力与面试考点
java·大数据·人工智能·数据分析
wuminyu1 天前
Kafka中sendfile与mmap实现机制解析
java·linux·c语言·jvm·c++
怕浪猫1 天前
FDE 如何正确解决现场项目工程性的问题
前端·后端·ai编程
西瓜太郎12341 天前
外层模型卡片与分组详情成功率不一致,应该怎么排查?
前端·typescript·go·软件工程·react
前端世界1 天前
Linux服务器实战:NTP时间同步、SELinux权限与rsyslog日志管理,一次搞懂三大运维问题
linux·运维·服务器
Android系统攻城狮1 天前
Linux Gstreamer深度解析之gst_audio_converter_new调用流程与实战(二十)
linux·运维·服务器·gstreamer音视频·音视频进阶
GreenTea1 天前
vLLM 与 SGLang KV Cache 底层实现机制深度调研报告
前端·后端·算法
考虑考虑1 天前
Java实现hmacsha256加密算法
java·后端·java ee
captain3761 天前
▲网络原理(2)-TCP
java·服务器·网络·tcp/ip·java-ee