嵌入式linux-僵尸进程?

news2025/2/28 11:20:26

1.僵尸进程

1.1 僵尸进程的由来和概念

通常,子进程结束之后,需要父进程为子进程进行回收,俗称“收尸”,则回收子进程占用的一些内存资源,父进程通过调用wait()(或其变体 waitpid()、waitid()等)函数回收子进程资源,归还给系统。

如果子进程先于父进程结束,此时父进程还未来得及给子进程“收尸”,那么此时子进程就变成了一个僵尸进程。

当父进程调用 wait()(或其变体,下文不再强调)为子进程“收尸”后,僵尸进程就会被内核彻底删除。另外一种情况,如果父进程并没有调用 wait()函数然后就退出了,那么此时 init 进程将会接管它的子进程并自动调用 wait(),故而从系统中移除僵尸进程。

僵尸进程有什么影响?
例如:如果父进程创建了某一子进程,子进程已经结束,而父进程还在正常运行,但父进程并未调用 wait()回收子进程,此时子进程变成一个僵尸进程。首先来说,这样的程序设计是有问题的,如果系统中存在大量的僵尸进程,它们势必会填满内核进程表,从而阻碍新进程的创建。需要注意的是,僵尸进程是无法通过信号将其杀死的,即使是“一击必杀”信号 SIGKILL 也无法将其杀死,那么这种情况下,只能杀死僵尸进程的父进程(或等待其父进程终止),这样 init 进程将会接管这些僵尸进程,从而将它们从系统中清理掉!所以,在我们的一个程序设计中,一定要监视子进程的状态变化,如果子进程终止了,要调用 wait()将其回收,避免僵尸进程。

编写示例代码,产生一个僵尸进程:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
	 /* 创建子进程 */
	 switch (fork()) 
	 {
		 case -1:
		 perror("fork error");
		 exit(-1);
		 
		 case 0:
		 /* 子进程 */
		 printf("子进程<%d>被创建\n", getpid());
		 sleep(1);
		 printf("子进程结束\n");
		 _exit(0);
		 
		 default:
		 /* 父进程 */
		 break;
	 }
	 for ( ; ; )
	 sleep(1);
	 exit(0);
}

在上述代码中,子进程已经退出,但其父进程并没调用 wait()为其“收尸”,使得子进程成为一个僵尸进程,使用命令ps -aux可以查看到该僵尸进程,测试结果如下:
在这里插入图片描述
在这里插入图片描述
通过命令可以查看到子进程 6042 依然存在,可以看到它的状态栏显示的是“Z”(zombie,僵尸),表示它是一个僵尸进程。僵尸进程无法被信号杀死,大家可以试试,要么等待其父进程终止、要么杀死其父进程,让 init 进程来处理,当我们杀死其父进程之后,僵尸进程也会被随之清理。

tips:想结束这个进程,直接启动线程的终端直接关掉再查看,就不会有了。

2. SIGCHLD 信号

2.1 信号,进程的回收

SIGCHLD 信号,前面有讲过一点,但当以下两种情况下,父进程会收到信号:

  1. 当父进程的某个子进程终止时,父进程会收到 SIGCHLD 信号;
  2. 当父进程的某个子进程因收到信号而停止(暂停运行)或恢复时,内核也可能向父进程发送该信号。

向大家说明一下:子进程的终止属于异步事件,父进程事先是无法预知的,如果父进程有自己需要做的事情,它不能一直wait()阻塞等待子进程终止(或轮训),这样父进程将啥事也做不了,那么有什么办法来解决这样的尴尬情况,当然有办法,那就是通过 SIGCHLD 信号。
这就是为什么,我们还要这重复信号的作用!!!

那既然子进程状态改变时(终止、暂停或恢复),父进程会收到 SIGCHLD 信号,SIGCHLD 信号的系统默认处理方式是将其忽略,所以我们就需要捕获它,所以我们要绑定信号处理函数,在信号处理函数中调用 wait()收回子进程,回收完毕之后再回到父进程自己的工作流程中。

下面给初学者一点技巧和方法:
问题:当调用信号处理函数时,会暂时将引发调用的信号添加到进程的信号掩码中(除非 sigaction()指定了 SA_NODEFER 标志),这样一来,当 SIGCHLD 信号处理函数正在为一个终止的子进程“收尸”时,如果相继有两个子进程终止,即使产生了两次 SIGCHLD 信号,父进程也只能捕获到一次SIGCHLD 信号,结果是,父进程的 SIGCHLD 信号处理函数每次只调用一次 wait(),那么就会导致有些僵尸进程成为“漏网之鱼”

解决: 在 SIGCHLD 信号处理函数中循环以非阻塞方式来调用 waitpid(),直至再无其它终止的子进程需要处理为止,所以,通常 SIGCHLD 信号处理函数内部代码如下所示:

while (waitpid(-1, NULL, WNOHANG) > 0)
continue;

直至 waitpid()返回 0,表明再无僵尸进程存在;或者返回-1,表明有错误发生。
应在创建任何子进程之前,为 SIGCHLD 信号绑定处理函数.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

static void wait_child(int sig)
{
	 /* 替子进程收尸 */
	 printf("父进程回收子进程\n");
	 while (waitpid(-1, NULL, WNOHANG) > 0)
	 continue;
}

int main(void)
{
	 struct sigaction sig = {0};
	 /* 为 SIGCHLD 信号绑定处理函数 */
	 sigemptyset(&sig.sa_mask);
	 sig.sa_handler = wait_child;
	 sig.sa_flags = 0;
	 if (-1 == sigaction(SIGCHLD, &sig, NULL)) 
	 {
		 perror("sigaction error");
		 exit(-1);
	 }
	 /* 创建子进程 */
	 switch (fork()) 
	 {
		 case -1:
		 perror("fork error");
		 exit(-1);
		 
		 case 0:
		 /* 子进程 */
		 printf("子进程<%d>被创建\n", getpid());
		 sleep(1);
		 printf("子进程结束\n");
		 _exit(0);
		 
		  default:
		 /* 父进程 */
		 break;
	 }
	 sleep(3);
	 exit(0);
}

在这里插入图片描述

本文参考正点原子的嵌入式LinuxC应用编程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/161463.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

公共数据 | CnOpenData中国省际铁路通行时间数据

中国省际铁路通行时间数据 一、数据简介 本数据来自南京大学长江产业经济研究院《全国统一大市场下的省际铁路交通研究报告》的附录部分。中国的铁路&#xff08;高铁&#xff09;建设取得了辉煌成果。但受铁路时刻众多、历史数据不容易搜集整理的限制&#xff0c;学术与政策研…

Linux进程状态和优先级

我的另一篇有关进程概念的博客&#xff1a;Linux 进程概念 目录 一、操作系统进程状态 1.1 运行状态(R) 1.2 阻塞状态(S) 1.3 挂起状态(S&#xff09; 二、Linux操作系统内核中的进程状态 2.1 进程状态种类 2.2 查看R和S进程状态 2.3 T和t状态 2.3.1 T状态 2.3.2 t状态…

python正则表达式与回溯绕过waf

1.正则表达式的背景 正则表达式的历史&#xff1a;美国的两个人类神经元研究者&#xff0c;使用特殊的符号描述。之后有一位科学家将这门技术引入了数学&#xff0c;将这门技术命名为正则表示式。 肯汤普森在编写UNIX系统时&#xff0c;将正则引入到了一个编辑器 绝大多数编…

GNN实战——KarateClub数据集

GNN&#xff1a;graph neural network 图神经网络&#xff0c;是⼀种连接模型&#xff0c;通过⽹络中节点之间的信息传递(message passing)的⽅式来获取图中的依存关系(dependence of graph)&#xff0c;GNN通过从节点任意深度的邻居来更新该节点状态&#xff0c;这个状态能够表…

Linux网络编程 第四天

目录 学习目标 多路IO-poll 多路IO-epoll 进阶epoll 用实验验证LT和ET模式 epoll反应堆 学习目标 1 了解poll函数 2 熟练使用epoll多路IO模型 3 了解epoll ET/LT触发模式并实现 4 理解epoll边缘非阻塞模式并实现 5 了解epoll反应堆模型设计思想 6 能看懂epoll反应堆模型的…

《C++程序设计原理与实践》笔记 第10章 输入/输出流

在本章和下一章中&#xff0c;我们将介绍C标准库中用于处理来自各种源的输入和输出的功能&#xff1a;I/O流。本章关注基本模型&#xff1a;如何读写单个值&#xff0c;以及如何打开和读写整个文件。下一章将介绍具体细节。 10.1 输入和输出 如果没有数据&#xff0c;计算就毫…

【正点原子FPGA连载】第十三章Linux内核移植 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十三章Linux内…

2023版软件测试学习路线图(超详细自学路线)

送福利了&#xff01;超详细的软件测试学习路线图来啦&#xff0c;2023版是首发哟&#xff01;软件测试学习路线图分为9个阶段&#xff0c;包含&#xff1a;软件测试环境配置和管理-->软件测试数据管理与数据库测试-->web前端测试技术-->通用软件测试技术-->Python…

回顾2022! 链上NFT精彩项目大盘点

过去一年&#xff0c;WEB3和元宇宙无疑吸引了一大波关注度和热度。不少知名品牌如耐克、GUCCI、百事可乐、星巴克、麦当劳等都纷纷加入这波浪潮&#xff0c;通过推出NFT、数字商品等&#xff0c;来尝试WEB3机制&#xff0c;进而塑造更好的用户消费体验和参与度。NFT兼具身份、功…

springboot,vue二手交易平台

开发工具&#xff1a;IDEA服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8项目构建&#xff1a;maven数据库&#xff1a;mysql5.7系统用户前台和管理后台两部分&#xff0c;项目采用前后端分离前端技术&#xff1a;vue elementUI服务端技术&#xff1a;springbootmybatis项目功…

0基础快速掌握正则表达式

背景 在日常开发中&#xff0c;我们经常会遇到使用正则表达式的场景&#xff0c;比如一些常见的表单校验&#xff0c;会让你匹配用户输入的手机号或者身份信息是否规范&#xff0c;这就可以用正则表达式去匹配。相信大多数人在碰到这种场景的时候都是直接去网上找&#xff0c;…

在 2023 ETH Denver 与 Cartesi 一起建设

我们非常高兴的加入了 2023年ETHDenver&#xff0c;参加了BUIDLathon 赛道和现场研讨会等活动。作为规模最大、持续时间最长的ETH 活动之一&#xff0c;我们将向热衷于为全球区块链生态系统做出贡献的新开发者社区分享 Cartesi 技术。你想在2023年#BUIDL 做一些有趣有意义的事情…

基于springboot的景区旅游信息管理系统(源代码+数据库)

基于springboot的景区旅游信息管理系统(源代码数据库) 一、系统介绍 本项目分为管理员与普通用户两种角色 用户登录 前台功能&#xff1a;旅游路线、旅游景点、旅游酒店、旅游车票、旅游保险、旅游策略管理员登录 后台功能&#xff1a;用户管理、旅游路线管理、旅游景点管理…

Codeforces Round #843 (Div. 2)(A~C,E)

A1/A2. Gardener and the Capybaras (easy version)三个字符串&#xff0c;按照顺序连在一起&#xff0c;三个字符串满足第二个字符串大于等于第一个和第三个&#xff0c;或者第二个字符串小于等于第一个和第三个&#xff0c;输出满足情况的三个字符串。思路&#xff1a;对于长…

ubuntu18.04系统下挂载新的机械硬盘

ubuntu18.04系统下挂载新的机械硬盘1.显示硬盘以及所属分区情况sudo fdisk -lDisk /dev/sda doesnt contain a valid partition table硬盘分区 对机械硬盘进行操作 sudo fdisk /dev/sda下图表示的是具体流程截图&#xff1a; The partition table has been altered!硬盘格式…

AWS RDS开启审计日志

问题 需要对AWS的RDS开启相关日志。先检查RDS是否开启日志&#xff0c;如下图&#xff1a; 选中一个数据库实例&#xff0c;查看到只开启了数据库的错误日志。但是&#xff0c;我们需要开启其他类型的审计日志。下面开始怎么样开启其他类型日志&#xff0c;来启用高级审计模…

corrosion 靶机(ffuf模糊测试,命令执行)

环境准备 靶机链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;c2j6 虚拟机网络链接模式&#xff1a;桥接模式 攻击机系统&#xff1a;kali linux 2022.03 信息收集 1.探测目标靶机开放端口和服务情况 2.用gobuster扫描目录&#xff0c;并访问 gobuster dir -…

手把手编译FFmpeg

支持centos8.6、ubuntu20.04 export 建议开始之前&#xff0c;弄一台干净的机子&#xff0c;或者系统恢复到出厂设置&#xff0c;否则容易出问题 然后设置动态库默认加载目录&#xff08;注意/usr/local/lib不是系统默认的路径&#xff0c;/lib和/usr/lib才是&#xff09; …

jsp库存管理管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 库存管理管理系统 是一套完善的系统源码&#xff0c;对理解JSP java serlvet MVC编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;以及相应配套的设计文档&#xff0c;系统主要采用B/S 模式开发。 通过本系统建设&#xff0c…

ArcGIS基础实验操作100例--实验97计算河道方向坡度

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 空间分析篇--实验97 计算河道方向坡度 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&…