一、进程基础

1. 进程核心定义

  • 进程是操作系统资源分配与调度的最小基本单位,是程序的一次动态执行过程。
  • 内核为每个运行程序创建task_struct 结构体(PCB 进程控制块),存储进程状态、PID、内存指针、资源占用等全部信息。
  • 进程正常结束 / 异常崩溃时,内核会回收 task_struct,避免资源泄漏。

2. 进程四大核心特征

  1. 动态性:有生命周期,动态创建、执行、消亡。
  2. 并发性:多进程可同时交替执行,共享 CPU 资源。
  3. 独立性:独立运行、独立拥有地址空间与系统资源。
  4. 异步性:进程按独立、不可预知的速度推进,相互制约。

3. 进程调度基础

  • 进程以时间片(默认 5ms) 轮转占用 CPU。
  • 就绪态进程进入运行队列,等待 CPU 调度;时间片用完回到就绪态。

二、程序与进程

1. 程序 vs 进程

对比维度 程序(Program) 进程(Process)
本质 静态指令集合,磁盘上的可执行文件(.exe) 程序的动态执行实例,有生命周期
资源占用 仅占磁盘空间,不占用 CPU / 内存 占用 CPU、内存、文件句柄、网络端口
状态 无状态 运行、睡眠、停止、僵尸等状态
独立性 多程序无直接关联 多进程独立地址空间,需 IPC 通信
生命周期 长期存储在磁盘 随程序启动创建,执行结束销毁
示例 磁盘上的浏览器.exe 双击打开的浏览器窗口

2. 程序与进程的关联

  • 一个程序可对应多个进程(多开软件)。
  • 多进程共享只读代码段,数据段、栈、堆相互独立。
  • 关闭进程不删除程序文件;删除程序文件,已运行进程可继续执行(依赖文件时报错)。

三、进程组成

1. PCB(进程控制块)

  • 操作系统管理进程的核心数据结构,是系统感知进程存在的唯一依据。
  • 存储内容:进程标识(PID/PPID)、状态、内存信息、资源占用、调度信息。

2. 文本段

  • 存储程序编译后的机器码指令,设置为只读(防止指令被篡改)。
  • 多进程运行同一程序可共享文本段,大幅节省内存。

3. 数据段

存储进程运行时的动态数据,分为 4 部分:

  1. 初始化数据段:已赋初值的全局变量 / 静态变量。
  2. 未初始化数据段(BSS):未赋初值的全局变量 / 静态变量。
  3. 堆(heap):动态内存分配(malloc/free),向上增长。
  4. 栈(stack):局部变量、函数调用,向下增长,系统自动管理。

四、Linux 进程三大类型

1. 交互进程

  • 由 Shell 启动,依赖终端,用户手动操作,前台运行。
  • 示例:ls、vim、浏览器。

2. 批处理进程

  • 无需用户交互,优先级低,后台按脚本 / 任务序列自动执行。
  • 示例:定时备份、日志处理脚本。

3. 守护进程(Daemon)

  • 系统启动时自动运行,脱离终端,随系统关闭终止。
  • 提供持续系统服务,名称常以 d 结尾(systemd、httpd)。

五、Linux 进程状态(基础 + 附加 + 转换)

1. 6 种基础状态

状态 标识 含义
运行 / 就绪态 R 正在 CPU 执行 或 等待 CPU 调度
可中断睡眠态 S 等待事件(I/O/ 信号),可被信号唤醒
不可中断睡眠态 D 等待关键硬件操作,不能被中断,保证数据完整
停止态 T 被 SIGSTOP 暂停,可被 SIGCONT 恢复
僵尸态 Z 进程终止,PCB 未被父进程回收
死亡态 X 资源完全释放,瞬间状态,无法观测

2. 附加状态标记

  • +:前台进程组,直接关联终端
  • l:多线程进程(LWP)
  • N:低优先级(NI>0)
  • <:高优先级(NI<0)
  • s:会话首进程(会话 leader)
  • L:持有文件 / 资源锁

3. 进程状态转换流程

  1. fork () 创建→就绪态 R
  2. 获得 CPU→运行态 R
  3. 时间片到→回到就绪态 R
  4. 等待事件→可中断睡眠 S / 不可中断睡眠 D
  5. 收到 SIGSTOP→停止态 T
  6. 进程退出→僵尸态 Z
  7. 父进程 wait () 回收→死亡态 X

六、进程 PID(进程标识)

1. PID 规则

  • PID 是≥1 的整数,0 号为特殊进程。
  • 系统最大 PID 数:sysctl kernel.pid_max 查看。
  • 进程信息存放在 /proc/[PID] 目录。

2. 三大特殊 PID

PID 进程名 核心作用
0 idle 系统首个进程,CPU 空闲时调度
1 init/systemd 系统初始化,回收孤儿进程
2 kthreadd 内核进程调度,管理内核任务(IO、内存回收)

七、Linux 进程管理常用命令(完整用法)

1. ps:进程快照查看

  • ps -ef:列出所有进程,全格式显示(PID/PPID/ 状态 / 命令)
  • ps -aux:按用户维度显示,包含 CPU / 内存占用率
  • ps -eo pid,comm:自定义输出字段
  • ps -l:长格式查看当前终端进程

2. top:实时进程监控

  • 动态显示 CPU、内存、负载、进程资源占用,支持排序。

3. htop:交互式进程工具

  • 可视化界面、支持鼠标、进程树展示,比 top 更易用。

4. 进程终止命令

  • kill -l:查看所有信号
  • kill -9 PID强制终止进程(SIGKILL,不可忽略)
  • kill -2 PID:中断进程(SIGINT,同 Ctrl+C)
  • killall 进程名:终止所有同名进程
  • killall -9 进程名:强制终止所有同名进程

5. 其他命令

  • pstree:树状展示进程父子关系
  • bg 作业号:挂起进程转后台运行
  • fg 作业号:后台进程转前台
  • nice -n 优先级 命令:启动时设置优先级
  • renice 优先级 -p PID:修改运行中进程优先级

八、多进程核心系统调用

1. 进程创建:fork ()

#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
  • 功能:复制父进程创建子进程,写时拷贝(Copy On Write)
    • 读操作:父子共享物理内存。
    • 写操作:重新映射新物理内存。
  • 返回值:
    • 父进程:返回子进程 PID(>0)
    • 子进程:返回0
    • 失败:返回 -1

2. 进程号获取

  • getpid():获取当前进程 PID
  • getppid():获取父进程 PID

3. 进程退出

函数 头文件 功能 区别
exit() stdlib.h 正常退出,刷新缓冲区 库函数
_exit() unistd.h 立即退出,不刷新缓冲区 系统调用

4. 子进程资源回收

wait ()(阻塞等待)

#include <sys/wait.h>
pid_t wait(int *wstatus);
  • 父进程阻塞,等待任意子进程退出,回收 PCB。
  • 状态解析宏:
    • WIFEXITED:判断正常退出
    • WEXITSTATUS:获取退出码
    • WIFSIGNALED:判断被信号终止
    • WTERMSIG:获取终止信号编号

waitpid ()(精准等待)

pid_t waitpid(pid_t pid, int *wstatus, int options);
  • pid:
    • -1:等待任意子进程
    • >0:等待指定 PID 子进程
  • options:
    • 0:阻塞
    • WNOHANG:非阻塞
    • WUNTRACED:捕获暂停状态
    • WCONTINUED:捕获恢复状态

5. 文件描述符重定向

  • dup(oldfd):复制文件描述符,系统分配最小可用 fd
  • dup2(oldfd, newfd):指定 newfd,已打开则自动关闭

6. exec 族函数(程序替换)

  • 功能:用新程序替换当前进程,PID 不变,成功无返回。
  • 常用:
    • execlp:按 PATH 查找程序,参数列表传入
    • execvp:按 PATH 查找程序,参数数组传入

九、三大特殊进程

1. 孤儿进程

  • 定义:父进程先终止,子进程成为孤儿。
  • 处理:被1 号进程(init/systemd) 收养。
  • 特点:正常运行,无系统危害,退出后自动回收。

2. 僵尸进程

  • 定义:子进程终止,父进程未调用 wait/waitpid,PCB 残留,状态 Z。
  • 危害:占用 PID 资源,大量僵尸会导致新进程无法创建。
  • 清理:
    • 预防:父进程主动回收子进程。
    • 清除:终止父进程,孤儿状态被 1 号进程回收。
    • 注意:kill -9 无法杀死僵尸进程(无运行实体)。

3. 守护进程

  • 核心特点:脱离终端、后台运行、父进程为 1 号、长期服务。
  • 创建流程:
    1. fork () → 父进程 exit (),子进程成孤儿
    2. setsid ():创建新会话,脱离原终端
    3. chdir ("/"):切换工作目录到根目录
    4. umask ():设置文件权限掩码
    5. 关闭继承的文件描述符
    6. 重定向输入输出到 /dev/null
    7. 启动服务逻辑

十、进程间通信(IPC)

Linux IPC 分三类:传统 IPC、System V IPC、BSD Socket

1. 无名管道(pipe)

  • 特点:
    • 内核实现,仅亲缘进程(父子 / 兄弟) 通信
    • 半双工,单向传输,大小 64KB
    • 不能 lseek 随机访问
  • 函数:int pipe(int pipefd[2])
    • pipefd [0]:读端
    • pipefd [1]:写端
  • 读写规则:
    • 读端存在:写满阻塞,有空间唤醒
    • 读端关闭:写触发 SIGPIPE(管道破裂)
    • 写端存在:无数据读阻塞
    • 写端关闭:无数据读返回 0

2. 有名管道(fifo)

  • 特点:
    • 任意进程可通信(亲缘 / 非亲缘)
    • 半双工,有管道文件,大小 64KB
  • 函数:mkfifo(路径名, 权限) 创建管道文件
  • 读写规则:
    • 读端未打开:写 open () 阻塞
    • 写端未打开:读 open () 阻塞

3. 信号(signal)

  • 本质:软件模拟中断,内核 / 进程可发送。
  • 处理方式:默认、忽略、捕捉(SIGKILL/SIGSTOP 不可捕捉 / 忽略)。
  • 常用信号:
    • SIGINT(2):Ctrl+C 中断
    • SIGKILL(9):强制终止
    • SIGSTOP(19):暂停
    • SIGCONT(18):恢复
    • SIGPIPE(13):管道破裂
  • 函数:signal() 绑定信号处理函数,kill() 发送信号。

4. 消息队列

  • 特点:内核维护,按消息类型收发,异步通信,默认 6KB。
  • 核心函数:
    • msgget():创建 / 获取队列
    • msgsnd():发送消息
    • msgrcv():接收消息
    • msgctl(IPC_RMID):删除队列

5. 共享内存

  • 特点:效率最高的 IPC,无需数据拷贝,多进程直接访问内核内存。
  • 核心函数:
    • shmget():创建共享内存
    • shmat():映射到进程地址空间
    • shmdt():取消映射
    • shmctl(IPC_RMID):删除共享内存

6. 信号量集

  • 作用:实现进程同步与互斥,控制共享资源访问。
  • 核心操作:
    • P 操作(申请):信号量 - 1,<0 则阻塞
    • V 操作(释放):信号量 + 1,>0 则唤醒等待进程
  • 核心函数:semget()/semop()/semctl()

7. IPC 适用场景

  • 无名管道:父子进程简单通信
  • 有名管道:任意进程本地通信
  • 信号:进程简单控制
  • 消息队列:异步、按类型收发
  • 共享内存:大数据、高频通信
  • 信号量:共享资源互斥访问
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐