【Linux】僵尸进程和孤儿进程

server/2024/10/23 0:59:24/




在这里插入图片描述




一、僵尸进程


何为僵尸进程?


        在 Unix/Linux 系统中,正常情况下,子进程是通过父进程创建的,且两者的运行是相互独立的,父进程永远无法预测子进程到底什么时候结束。当一个进程调用 exit 命令结束自己的生命时,其实它并没有真正的被销毁,操作系统内核只是释放了该进程的所有资源,包括打开的文件、占用的内存等(比如malloc占用内存不释放,也会在此时释放),但是留下一个数据结构(只保留 struct task_struct 一个空壳子),这个结构保留了一定的信息(包括进程号 the process ID,退出状态,运行时间….),这些信息直到父进程通过 wait() / waitpid() 来取时才释放。这样设计的目的主要是保证父进程能够获取到子进程结束时的状态信息(父进程回收僵尸进程的时候可以根据 退出码 确定子进程的退出原因)。


而只剩下一个保留着退出状态等信息的数据结构的进程,即为僵尸进程



僵尸进程的危害


占用进程号:系统所能使用的进程号是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程僵尸进程会占用系统的进程表条目,如果系统中有大量僵尸进程存在而不被清理,可能会导致系统不能创建新的进程。这是因为进程ID(PID)是有限的,如果大部分都被僵尸进程占用,那么就没有足够的PID分配给新创建的进程。

有人说僵尸进程会占用内存:实际上,僵尸进程不占有任何内存空间,其本身并不会直接导致内存泄漏。内存泄漏更多是程序设计的问题,而不是操作系统层面的问题。僵尸进程最大的危害是占用进程号,导致系统无法产生新进程。



僵尸进程的的创建


子进程在 exit() 之后,父进程没有来得及处理,这时用 ps 命令就能看到子进程的状态是“Z”,即为僵尸状态

创造一个僵尸进程思路:保证父进程不死,子进程创建后使用 exit(0) 退出

这条 71780 号进程即为状态 Z 的僵尸进程(defunct 意思是已失效)

在这里插入图片描述


#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>int main(){printf("I am 父进程, pid : %d\n", getpid());pid_t id = fork();// 父进程:死循环维持生命if(id > 0){printf("这是新建的子进程: %d\n", id);while(1){printf("I am 父进程, pid : %d\n", getpid());sleep(1);};}// 子进程: 创建后退出,形成僵尸进程else if(id == 0){exit(0);		}return 0;
}


二、孤儿进程


何为孤儿进程?


孤儿进程:当某个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。孤儿进程并不是无父无母的 “野孩子”,而是会被系统默认的 init 进程所收养。(或者是现代 Linux 系统中的 systemd 进程,在早期的 Unix 系统中通常是 PID = 1init 进程)


        当一个进程成为孤儿进程后,它的直接父进程变成了 init systemd ,这样可以确保每个进程都有一个父进程。 init systemd 作为“养父”,不会像真正的父进程那样去管理和控制孤儿进程的行为,但它会负责清理孤儿进程的退出状态。也就是说,当孤儿进程最终终止时, init systemd 会接收到孤儿进程的退出通知,并更新系统的进程表。即 “养父” 会默认管理孤儿进程的退出状态,会帮它回收,不会使其变成僵尸进程,因此孤儿进程并不会有什么危害。



三、如何杀掉僵尸进程?


注意:僵尸进程不能被系统的 kill -9 信号杀死(SIGKILL只能发送给仍在运行的进程) (因为僵尸进程已经死了,是死掉的进程,当然也不能响应系统的信号)

1、被父进程回收

通过 wait() /waitpid() 才释放

2、可以杀掉它的父进程

        ​父进程被杀掉之后,僵尸进程会变成孤儿进程,孤儿进程会被系统的 1 号进程收留(即 Init 进程),1 号进程会检查该进程是不是僵尸进程,如果是的话则会将进程回收。


3、设置信号处理器

    父进程可以在创建子进程之前设置SIGCHLD信号的处理函数,当子进程结束时,操作系统会向父进程发送SIGCHLD信号。父进程可以在这个信号的处理函数中调用wait()waitpid()来清理僵尸进程。

#include <signal.h>
//...
void handle_child(int signum) {int status;waitpid(-1, &status, WNOHANG); // 非阻塞方式回收
}// 设置信号处理器
signal(SIGCHLD, handle_child);



http://www.ppmy.cn/server/134038.html

相关文章

excel筛选多个单元格内容

通常情况下&#xff0c;excel单元格筛选时&#xff0c;只筛选一个条件&#xff0c;如果要筛选多个条件&#xff0c;可以如下操作&#xff1a; 字符串中间用空格分隔就行。

【JAVA毕业设计】基于Vue和SpringBoot的图书个性化推荐系统

本文项目编号 T 015 &#xff0c;文末自助获取源码 \color{red}{T015&#xff0c;文末自助获取源码} T015&#xff0c;文末自助获取源码 目录 一、系统介绍1.1 业务分析1.2 用例设计1.3 时序设计 二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究…

运行第一个go程序

安装Go环境&#xff1a; 首先&#xff0c;确保你的计算机上已经安装了Go。你可以从Go的官方网站(https://golang.org/dl/)下载适合你操作系统的安装包&#xff0c;并按照指示进行安装。 安装完成后&#xff0c;可以通过在命令行输入 go version 来检查是否安装成功。如果安装正…

springboot基于微信小程序的“热岛”志愿者服务平台

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图文章目录 前言 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 当今社会已经步入了科学技术进步和经济社会快速发展的新时期&#xff0c;国际信息和学术交流也不…

【Golang】Go语言web框架Gin响应客户端有哪些方式

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

Golang | Leetcode Golang题解之第479题最大回文数乘积

题目&#xff1a; 题解&#xff1a; func largestPalindrome(n int) int {if n 1 {return 9}upper : int(math.Pow10(n)) - 1for left : upper; ; left-- { // 枚举回文数的左半部分p : leftfor x : left; x > 0; x / 10 {p p*10 x%10 // 翻转左半部分到其自身末尾&…

网络爬虫-数美滑块验证码

仅供研究学习使用。 今天带来的是数美滑块验证码的逆向 目标站 --> 传送门 解决此类验证码 首先要解决滑动距离的判定 无论是使用selenium还是使用协议的方式来破解 都绕不开滑动距离的识别 滑动距离可以参考以前我博客上的方式&#xff0c;或者找一找开源的一些算法&am…

六、LogicFlow 自定义业务边 Edge

前言 经过前面的文章讲解&#xff0c;目前已经实现了节点拖拽到画布中&#xff0c;并且也实现了节点之间的基础连线&#xff0c;到这里也算是入了门&#xff0c;接下来继续探究新学习新的功能&#xff0c;以满足新的需求&#xff0c;那么这一章就会学习如何更改两节点之间的连…