news 2026/2/10 6:20:33

Linux 进程管理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux 进程管理

在 Linux C/C++ 开发中,进程管理是系统编程的核心知识点之一。从父子进程的创建、进程的终止到僵尸进程的避免,每一个环节都影响着程序的稳定性。本文将从基础概念到实践代码,详细讲解 Linux 进程管理的关键技术。

一、父子进程:写时复制的 “副本关系”

当我们通过fork()创建子进程时,子进程是父进程的 “复制副本”—— 但在现代 Linux(2.6 版本后,如 Ubuntu 18.04 使用的 Linux 5.4 内核)中,这个 “复制” 并非完全拷贝,而是采用了 ** 写时复制(Copy-on-Write,COW)** 机制:

  • 初始状态:子进程与父进程共享同一块内存空间(包括代码段、数据段、堆、栈),内核仅为子进程创建独立的 PCB(进程控制块)。
  • 写操作触发拷贝:当子进程修改某块内存(如变量、数组)时,内核才会为子进程分配新的内存空间,并将修改的内容拷贝到新空间中,实现 “按需拷贝”。

这种机制既节省了内存资源,又提升了fork()的效率。

二、进程的终止:8 种情况分类

进程的终止分为 “正常终止” 和 “异常终止” 两类,共 8 种场景:

终止类型具体场景说明
正常终止1.main函数中执行return会触发进程退出,返回值作为进程退出状态
2. 调用exit()函数库函数,会执行 I/O 清理(刷新缓存)、关闭打开的文件,再终止进程
3. 调用_Exit()函数系统调用,仅关闭打开的文件,不执行 I/O 清理(缓存数据会丢失)
4. 主线程退出主线程结束后,进程会随之终止
5. 主线程调用pthread_exit仅主线程退出,进程不会终止(需所有线程结束)
异常终止6. 调用abort()函数触发SIGABRT信号,强制进程终止
7. 通过signal/kill发送终止信号kill -9 pid强制杀死进程
8. 最后一个线程被pthread_cancel取消所有线程结束后,进程终止

三、退出后的进程:僵尸与孤儿

进程退出后并非直接 “消失”,而是会进入特殊状态:

1. 僵尸进程(Zombie Process)

  • 产生条件:父进程创建子进程后,子进程先退出,但父进程未调用wait/waitpid回收子进程。
  • 表现:子进程的用户内存已释放,但内核中的 PCB(包含进程 PID、退出状态等)未被释放,进程状态标识为Z(可通过ps aux | grep Z查看)。
  • 危害:长期积累的僵尸进程会占用内核内存,导致系统资源不足、稳定性下降。

2. 孤儿进程(Orphan Process)

  • 产生条件:父进程创建子进程后,父进程先退出,子进程会被系统进程(如initsystemd)接管。
  • 表现:子进程的新父进程会自动回收其资源,因此孤儿进程不会造成资源泄漏,无需额外处理。

四、进程退出函数:exit 与_exit 的区别

进程退出的核心函数是exit(库函数)和_exit(系统调用),二者的差异是面试高频考点:

函数类型核心行为适用场景
exit(int status)库函数1. 执行atexit注册的清理函数;2. 刷新 I/O 缓存;3. 关闭打开的文件;4. 调用_exit终止进程需保证数据完整写入(如文件操作后)
_exit(int status)系统调用1. 关闭打开的文件;2. 直接终止进程(不处理缓存 / 清理函数)紧急退出(如信号处理函数中)

示例

c

运行

#include <stdio.h> #include <stdlib.h> #include <unistd.h> int main() { printf("使用exit退出(会刷新缓存)"); exit(EXIT_SUCCESS); // 输出会被打印 } // 对比: int main() { printf("使用_exit退出(不刷新缓存)"); _exit(EXIT_SUCCESS); // 输出不会被打印(缓存未刷新) }

五、进程回收:wait/waitpid 解决僵尸问题

为了避免僵尸进程,父进程必须主动回收子进程,核心函数是waitwaitpid

1. wait 函数

c

运行

pid_t wait(int *status);
  • 功能:阻塞等待任意一个子进程退出,并回收其 PCB。
  • 参数status:存储子进程的退出状态(若不需要,传NULL)。
  • 返回值:成功返回被回收子进程的 PID;失败返回-1(如无待回收子进程)。

解析退出状态:需通过宏函数提取status中的信息:

  • WIFEXITED(status):判断子进程是否正常退出(返回非 0 表示正常)。
  • WEXITSTATUS(status):提取子进程的退出值(仅当WIFEXITED为真时有效)。
  • WIFSIGNALED(status):判断子进程是否被信号终止。
  • WTERMSIG(status):提取终止子进程的信号编号。

2. 实践代码:回收子进程并处理退出状态

c

运行

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> int main() { pid_t pid = fork(); if (pid == -1) { perror("fork失败"); exit(1); } if (pid == 0) { // 子进程:执行任务后退出 printf("子进程(pid=%d)执行中...\n", getpid()); sleep(2); exit(5); // 正常退出,退出值为5 } else { // 父进程:回收子进程 int status; pid_t child_pid = wait(&status); if (child_pid == -1) { perror("wait失败"); exit(1); } // 解析退出状态 if (WIFEXITED(status)) { printf("回收子进程(pid=%d),退出值:%d\n", child_pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("回收子进程(pid=%d),被信号%d终止\n", child_pid, WTERMSIG(status)); } } return 0; }

运行结果

plaintext

子进程(pid=12345)执行中... 回收子进程(pid=12345),退出值:5

3. 批量回收:waitpid 循环处理多子进程

若父进程创建了多个子进程,需循环调用waitpid回收所有子进程:

c

运行

// 循环回收所有子进程 while (waitpid(-1, &status, WNOHANG) > 0) { // 处理退出状态... }
  • waitpid(-1, &status, WNOHANG)-1表示回收任意子进程,WNOHANG表示非阻塞(无待回收子进程时直接返回 0)。

六、实战:如何查看僵尸进程?

通过pstop命令可查看系统中的僵尸进程:

  1. ps 命令

    bash

    运行

    ps aux | grep Z
    输出中状态为Z的进程即为僵尸进程。
  2. top 命令:进入top后,按z可高亮显示僵尸进程,或查看 “Zombie” 统计项(若大于 0,说明存在僵尸进程)。

总结

Linux 进程管理的核心是 “创建 - 终止 - 回收” 的闭环:

  1. fork()创建子进程,利用写时复制节省资源;
  2. 子进程通过exit/_exit正常退出,或被信号异常终止;
  3. 父进程必须通过wait/waitpid回收子进程,避免僵尸进程;
  4. 孤儿进程由系统接管,无需额外处理。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/5 2:54:58

JS核心语法

特性varletconst块级作用域❌&#xff08;函数级作用域&#xff09;✅✅变量提升✅&#xff08;可先使用后声明&#xff09;❌&#xff08;暂时性死区&#xff09;❌&#xff08;暂时性死区&#xff09;重复声明✅❌❌重新赋值✅✅❌&#xff08;声明时必须赋值&#xff09;// …

作者头像 李华
网站建设 2026/2/4 22:02:23

分公司组织架构图在线设计 总部分支管理模板

良功绘图网站 (https://www.lghuitu.com ) 在企业规模化发展的进程中&#xff0c;分公司的设立成为拓展市场、优化资源配置的重要举措。而总部分支之间的高效协同&#xff0c;离不开清晰、科学的组织架构作为支撑。分公司组织架构图作为直观呈现管理层级、部门设置、权责划分的…

作者头像 李华
网站建设 2026/2/5 16:40:29

KD-Tree的查询原理

好的&#xff0c;让我详细解释KD-Tree的查询原理&#xff0c;以及为什么它能将时间复杂度从O(n)降到O(log n)。 KD-Tree的基本结构 KD-Tree&#xff08;k-dimensional tree&#xff09;是一种用于多维空间的数据结构&#xff0c;特别适合范围搜索和最近邻搜索。 构建过程示例…

作者头像 李华
网站建设 2026/2/6 18:53:27

基于Mask R-CNN的道路路面损伤自动检测与分类研究

1. 基于Mask R-CNN的道路路面损伤自动检测与分类研究 1.1. 引言 随着城市化进程的加速&#xff0c;道路基础设施的维护变得越来越重要。传统的人工检测方法效率低下、成本高昂&#xff0c;且存在安全隐患。&#x1f6a7; 近年来&#xff0c;计算机视觉技术的快速发展为道路路…

作者头像 李华
网站建设 2026/2/5 13:34:03

最近在研究高速列车的主动悬挂系统,发现H无穷控制策略在这个领域挺有意思的。今天就来聊聊基于H无穷控制策略的横摆半车9自由度高速列车主动悬挂

基于H无穷控制策略的横摆半车9自由度高速列车主动悬挂首先&#xff0c;我们得明白什么是H无穷控制。简单来说&#xff0c;H无穷控制是一种鲁棒控制方法&#xff0c;能够在系统存在不确定性和外部干扰的情况下&#xff0c;保证系统的稳定性和性能。对于高速列车这种复杂系统&…

作者头像 李华
网站建设 2026/2/6 23:33:01

Ubuntu硬盘空间不够?一文带你理清过程的根分区无损扩容实战指南

复杂分区布局下的 Ubuntu 根目录无损扩容实践&#xff1a;从引导参数调试到扇区移位 摘要 本文详细记录了在一块 1TB NVMe 固态硬盘&#xff08;WD_BLACK SN770&#xff09;上&#xff0c;解决 Ubuntu 根分区&#xff08;/&#xff09;空间不足问题的全过程。本次扩容的特殊性在…

作者头像 李华