Linux 僵尸进程与孤儿进程

devtools/2025/2/12 2:44:00/

Linux 僵尸进程与孤儿进程

      • 1. 僵尸进程 (Zombie Process)
        • 1.1 什么是僵尸进程
        • 1.2 僵尸进程的产生
        • 1.3 僵尸进程的危害
        • 1.4 如何处理僵尸进程
      • 2. 孤儿进程 (Orphan Process)
        • 2.1 什么是孤儿进程
        • 2.2 孤儿进程的特点
        • 2.3 孤儿进程的应用

在 Linux 系统中,进程是资源分配和调度的基本单位。每个进程都有其生命周期,从创建到终止。然而,当一个进程终止时,它并不会立即从系统中完全移除,而是会经历一些特殊的状态,例如僵尸进程和孤儿进程

在这里插入图片描述

1. 僵尸进程 (Zombie Process)

1.1 什么是僵尸进程

当一个进程调用 exit() 函数正常或异常终止时,内核会将进程的状态设置为终止状态,并保留进程的一些信息,例如退出码、CPU 使用时间等。此时,进程的绝大部分资源(如内存、文件描述符等)都会被释放,但进程的进程控制块(PCB)仍然保留在系统中,以便父进程可以获取子进程的退出信息。这种处于终止状态但仍然占用少量系统资源的进程被称为僵尸进程。

1.2 僵尸进程的产生

当一个父进程创建了一个子进程后,子进程终止时,会向父进程发送一个 SIGCHLD 信号。父进程可以选择忽略该信号,也可以通过调用 wait()waitpid() 等函数来处理子进程的退出。如果父进程没有及时处理子进程的退出信息,那么子进程就会变成僵尸进程。

1.3 僵尸进程的危害

僵尸进程本身不会占用大量的系统资源,但如果系统中存在大量的僵尸进程,可能会导致以下问题:

  • 进程 ID 耗尽: 每个进程都需要一个唯一的进程 ID。如果大量的进程终止后变成僵尸进程,而父进程又没有及时回收它们,那么系统中的可用进程 ID 可能会被耗尽,导致无法创建新的进程。
  • 系统资源浪费: 僵尸进程虽然占用的资源不多,但毕竟还是占用着一些系统资源,例如进程表项。如果僵尸进程过多,可能会导致系统资源浪费。
1.4 如何处理僵尸进程

处理僵尸进程的方法主要有两种:

  • 等待子进程结束: 父进程应该及时调用 wait()waitpid() 等函数来等待子进程结束,并获取子进程的退出信息。这样可以避免子进程变成僵尸进程。
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {pid_t pid;int status;pid = fork();if (pid == 0) {// 子进程printf("Child process is running...\n");exit(0);} else if (pid > 0) {// 父进程printf("Parent process is waiting for child process...\n");wait(&status); // 等待子进程结束printf("Child process has finished.\n");} else {// 创建子进程失败perror("fork failed");return 1;}// 判断子进程退出状态if (WIFEXITED(status)) {// 子进程正常退出printf("Child process exited normally with status %d\n", WEXITSTATUS(status));} else if (WIFSIGNALED(status)) {// 子进程被信号终止printf("Child process terminated by signal %d\n", WTERMSIG(status));}return 0;
}

在上面的代码中,我们使用了 WIFEXITED()WIFSIGNALED() 两个宏来判断子进程的退出状态。

  • WIFEXITED(status):如果子进程是正常退出(通过调用 exit()return ),则返回 true。此时,可以通过 WEXITSTATUS(status) 宏来获取子进程的退出码。

  • WIFSIGNALED(status):如果子进程是被信号终止的,则返回 true。此时,可以通过 WTERMSIG(status) 宏来获取导致子进程终止的信号编号。

  • 杀死父进程: 如果父进程不再需要子进程的信息,可以直接杀死父进程。这样,子进程就会被 init 进程接管,并由 init 进程负责回收。

此外,还可以通过以下方法避免僵尸进程:

  • 忽略 SIGCHLD 信号: 父进程可以通过 signal(SIGCHLD, SIG_IGN) 通知内核,表示自己对子进程的退出不感兴趣。这样,子进程退出后会立即释放数据结构,不会变成僵尸进程。
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {pid_t pid;pid = fork();if (pid == 0) {// 子进程printf("Child process is running...\n");exit(0);} else if (pid > 0) {// 父进程printf("Parent process is running...\n");signal(SIGCHLD, SIG_IGN); // 忽略 SIGCHLD 信号while (1) {// 父进程执行其他任务sleep(1);}} else {// 创建子进程失败perror("fork failed");return 1;}return 0;
}
  • 使用 wait3()wait4() 函数: 这两个函数提供了更多的选项来处理子进程的退出状态,例如可以获取子进程的资源使用情况。
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {pid_t pid;int status;struct rusage usage;pid = fork();if (pid == 0) {// 子进程printf("Child process is running...\n");exit(0);} else if (pid > 0) {// 父进程printf("Parent process is waiting for child process...\n");wait4(pid, &status, 0, &usage); // 等待子进程结束,并获取资源使用情况printf("Child process has finished.\n");} else {// 创建子进程失败perror("fork failed");return 1;}return 0;
}

2. 孤儿进程 (Orphan Process)

2.1 什么是孤儿进程

当一个父进程在子进程之前终止时,子进程就会变成孤儿进程。此时,init 进程(进程 ID 为 1)会自动接管孤儿进程,成为它们的父进程。

2.2 孤儿进程的特点
  • 父进程: 孤儿进程的父进程是 init 进程。
  • 生命周期: 孤儿进程的生命周期与 init 进程相同。当 init 进程终止时,所有孤儿进程也会被终止。
  • 资源回收: init 进程会负责回收孤儿进程的资源,因此孤儿进程不会像僵尸进程那样占用系统资源。
2.3 孤儿进程的应用

孤儿进程在某些场景下非常有用。例如,守护进程通常会创建子进程来执行一些后台任务,而守护进程本身则会继续运行。在这种情况下,子进程就可能成为孤儿进程。

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>int main() {pid_t pid;pid = fork();if (pid == 0) {// 子进程printf("Child process is running...\n");while (1) {// 子进程执行一些任务sleep(1);}} else if (pid > 0) {// 父进程printf("Parent process is exiting...\n");exit(0); // 父进程退出} else {// 创建子进程失败perror("fork failed");return 1;}return 0;
}

http://www.ppmy.cn/devtools/158084.html

相关文章

【图片转换PDF】多个文件夹里图片逐个批量转换成多个pdf软件,子文件夹单独合并转换,子文件夹单独批量转换,基于Py的解决方案

建筑设计公司在项目执行过程中&#xff0c;会产生大量的设计图纸、效果图、实景照片等图片资料。这些资料按照项目名称、阶段、专业等维度存放在多个文件夹和子文件夹中。 操作需求&#xff1a;为了方便内部管理和向客户交付完整的设计方案&#xff0c;公司需要将每个项目文件…

我准备做一个24H的摄像机模拟器,用录像视频模拟实时画面,如果能支持时间水印就更好了

之前我不是搞了一个摄像机模拟器吗《用EasyRTSPServer模拟摄像机RTSP流实现RTSP摄像机模拟器 》&#xff0c;搞的比较简单&#xff0c;就是用视频文件模拟摄像机的画面&#xff0c;那个只能简单用来做个IPC模拟&#xff0c;给开发者用用或者给调研的人看看可行性&#xff0c;实…

Transformer基础 多头自注意力机制

# 1. **自注意力机制**&#xff1a;Transformer通过自注意力机制能够高效地计算序列内所有元素之间的关系&#xff0c;这使得模型能够捕捉到长距离依赖&#xff0c;无论这些依赖的距离有多远。 # 2. **并行化处理**&#xff1a;与RNN不同&#xff0c;Transformer可以同时处理整…

如何使用Socket编程在Python中实现实时聊天应用

在现代的网络应用中&#xff0c;实时聊天功能成为了不可或缺的一部分。从社交平台到在线客服系统&#xff0c;实时聊天应用广泛存在。Python提供了强大的socket库&#xff0c;可以帮助我们轻松实现基于TCP协议的实时聊天功能。本文将介绍如何通过Socket编程在Python中实现一个简…

Git―分支管理

Git ⛅创建&切换&合并分支⛅删除分支⛅合并冲突⛅合并模式⛅Bug 分支⛅强制删除分支 master → 主分支 # 查看本地所有分支 git branch分支前面的*, 代表当前所在的分支 图中当前所在的分支为master ⛅创建&切换&合并分支 # 创建分支 git branch "bra…

Spring框架学习大纲

Spring框架学习大纲 一、Spring基础入门 Spring概述 Spring框架发展历史与核心优势Spring核心模块组成&#xff08;IoC、AOP、Data Access、Web MVC等&#xff09;Spring与传统Java EE开发对比 控制反转&#xff08;IoC&#xff09;与依赖注入&#xff08;DI&#xff09; IoC…

贪心算法_翻硬币

蓝桥账户中心 依次遍历 不符合条件就反转 题目要干嘛 你就干嘛 #include <bits/stdc.h>#define endl \n using namespace std;int main() {ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); string s; cin >> s;string t; cin >> t;int ret 0;for ( i…

Android双屏异显Presentation接口使用说明

在点餐、收银、KTV等场景,对于双屏异显的需求是非常多的,首先可以节省硬件成本。而现在的智能板卡很多运行Android系统,从Android4.2开始支持WiFi Display(Miracast)功能后,就开始支持双屏异显Presentation这套应用层接口了,下面以Android5.1系统来说明这套接口的使用要…