当前位置: 首页 > news >正文

嵌入式 Linux 的僵尸进程是什么?

目录

1、什么是僵尸进程?

2、僵尸进程的目的

3、怎么避免僵尸进程?

4、僵尸进程的处理方法

4.1 wait()连接

4.2 waitpid()函数 

 

1、什么是僵尸进程?

  首先内核会释放终止进程(调用了 exit 系统调用)所使用的所有存储区,关闭所有打开的文件 等,但内核为每一个终止子进程保存了一定量的信息。这些信息至少包括进程 ID,进程的终止状 态,以及该进程使用的 CPU 时间,所以当终止子进程的父进程调用 wait 或 waitpid 时就可以得 到这些信息。

  而僵尸进程就是指:一个进程执行了 exit 系统调用退出,而其父进程并没有为它收尸(调用 wait 或 waitpid 来获得它的结束状态)的进程。 任何一个子进程(init 除外)在 exit 后并非马上就消失,而是留下一个称外僵尸进程的数据结构, 等待父进程处理。这是每个子进程都必需经历的阶段。另外子进程退出的时候会向其父进程发送一 个 SIGCHLD 信号。

2、僵尸进程的目的

  设置僵死状态的目的是维护子进程的信息,以便父进程在以后某个时候获取。这些信息至少包 括进程 ID,进程的终止状态,以及该进程使用的 CPU 时间,所以当终止子进程的父进程调用 wait 或 waitpid 时就可以得到这些信息。如果一个进程终止,而该进程有子进程处于僵尸状态,那么 它的所有僵尸子进程的父进程 ID 将被重置为 1(init 进程)。继承这些子进程的 init 进程将清 理它们(也就是说 init 进程将 wait 它们,从而去除它们的僵尸状态)。

3、怎么避免僵尸进程?

1.通过 signal(SIGCHLD, SIG_IGN)通知内核对子进程的结束不关心,由内核回收。如果不 想让父进程挂起,可以在父进程中加入一条语句:signal(SIGCHLD,SIG_IGN);表示父进程忽略 SIGCHLD 信号,该信号是子进程退出的时候向父进程发送的。

2.父进程调用 wait/waitpid 等函数等待子进程结束,如果尚无子进程退出 wait 会导致父进 程阻塞。waitpid 可以通过传递 WNOHANG 使父进程不阻塞立即返回。

3.如果父进程很忙可以用 signal 注册信号处理函数,在信号处理函数调用 wait/waitpid 等待子进程退出。

4.通过两次调用 fork。父进程首先调用 fork 创建一个子进程然后 waitpid 等待子进程退出, 子进程再 fork 一个孙进程后退出。这样子进程退出后会被父进程等待回收,而对于孙子进程其父 进程已经退出所以孙进程成为一个孤儿进程,孤儿进程由 init 进程接管,孙进程结束后,init 会等待回收。

第一种方法忽略 SIGCHLD 信号,这常用于并发服务器的性能的一个技巧因为并发服务器常常 fork 很多子进程,子进程终结之后需要服务器进程去 wait 清理资源。如果将此信号的处理方式 设为忽略,可让内核把僵尸子进程转交给 init 进程去处理,省去了大量僵尸进程占用系统资源。

4、僵尸进程的处理方法

4.1 wait()连接

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);

进程一旦调用了 wait,就立即阻塞自己,由 wait 自动分析是否当前进程的某个子进程已经退出,如果让它找 到了这样一个已经变成僵尸的子进程,wait 就会收集这个子进程的信息,并把它彻底销毁后返回;如果没有找 到这样一个子进程,wait 就会一直阻塞在这里,直到有一个出现为止。 参数 status 用来保存被收集进程退出时的一些状态,它是一个指向 int 类型的指针。但如果我们对这个子进程 是如何死掉的毫不在意,只想把这个僵尸进程消灭掉,(事实上绝大多数情况下,我们都会这样想),我们就可 以设定这个参数为 NULL,就象下面这样:

pid = wait(NULL);

如果成功,wait 会返回被收集的子进程的进程 ID,如果调用进程没有子进程,调用就会失败,此时 wait 返回 -1,同时 errno 被置为 ECHILD。

  1. wait 系统调用会使父进程暂停执行,直到它的一个子进程结束为止。
  2. 返回的是子进程的 PID,它通常是结束的子进程
  3. 状态信息允许父进程判定子进程的退出状态,即从子进程的 main 函数返回的值或子进程中 exit 语句的退 出码。
  4.  如果 status 不是一个空指针,状态信息将被写入它指向的位置

4.2 waitpid()函数 

#include #include pid_t waitpid(pid_t pid, int *status, int options);

参数:

status:如果不是空,会把状态信息写到它指向的位置,与 wait 一样

options:允许改变 waitpid 的行为,最有用的一个选项是 WNOHANG,它的作用是防止 waitpid 把调用者的执行挂起

返回值:如果成功返回等待子进程的 ID,失败返回-1

对于 waitpid 的 pid 参数的解释与其值有关:

pid == -1 等待任一子进程。于是在这一功能方面 waitpid 与 wait 等效。

pid > 0 等待其进程 I D 与 p i d 相等的子进程。

pid == 0 等待其组 I D 等于调用进程的组 I D 的任一子进程。换句话说是与调用者进程同在一个组的进程。

pid < -1 等待其组 I D 等于 p i d 的绝对值的任一子进程 wait 与 waitpid 区别:

 在一个子进程终止前, wait 使其调用者阻塞,而 waitpid 有一选择项,可使调用者不阻塞。

 waitpid 并不等待第一个终止的子进程—它有若干个选择项,可以控制它所等待的特定进程。

 实际上 wait 函数是 waitpid 函数的一个特例。waitpid(-1, &status, 0);

示例:如下代码会创建100个子进程,但是父进程并没有等待他们结束,所以在父进程退出前会有100个僵尸进程;

#include <stdio.h> 
#include <unistd.h> 
int main() { int i; pid_t pid; for(i=0; i<100; i++) { pid = fork(); if(pid == 0) break; } if(pid>0) { printf("press Enter to exit..."); getchar(); } return 0; 
}
其中一个解决方法即是编写一个SIGCHLD信号处理程序来调用wait/waitpid来等待子进程返回。
#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
void wait4children(int signo) { int status; wait(&status); 
} int main() { int i; pid_t pid; signal(SIGCHLD, wait4children); for(i=0; i<100; i++) { pid = fork(); if(pid == 0) break; } if(pid>0) { printf("press Enter to exit..."); getchar(); } return 0; 
}

 所以最佳的方案如下:

#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/wait.h> void wait4children(int signo) { int status; pid_t pid;while(pid=waitpid(-1, &status, WNOHANG) > 0){
//if (WIFEXITED(status))// printf("------------child %d exit %d\n", pid, WEXITSTATUS(status));// else if (WIFSIGNALED(status))// printf("child %d cancel signal %d\n", pid, WTERMSIG(status));
} 
} int main() { int i; pid_t pid; signal(SIGCHLD, wait4children); for(i=0; i<100; i++) { pid = fork(); if(pid == 0) break; } if(pid>0) { printf("press Enter to exit..."); getchar(); } return 0; 
}

这里使用 waitpid 而不是使用 wait 的原因在于:我们在一个循环内调用 waitpid,以获取 所有已终止子进程的状态。我们必须指定 WNOHANG 选项,它告诉 waitpid 在有尚未终止的子进程 在运行时不要阻塞。我们不能在循环内调用 wait,因为没有办法防止 wait 在正运行的子进程尚 有未终止时阻塞。

相关文章:

嵌入式 Linux 的僵尸进程是什么?

目录 1、什么是僵尸进程&#xff1f; 2、僵尸进程的目的 3、怎么避免僵尸进程&#xff1f; 4、僵尸进程的处理方法 4.1 wait&#xff08;&#xff09;连接 4.2 waitpid&#xff08;&#xff09;函数 1、什么是僵尸进程&#xff1f; 首先内核会释放终止进程(调用了 exit …...

【刷题笔记】笔记一

1.自守数牛客链接解析&#xff1a;1.自守数的结尾肯定是 0&#xff0c;1&#xff0c;5&#xff0c;62.把数字转换为string类&#xff08;方便比较&#xff09;3.直接find在s2 里面 使用find查找另一个即可。#include <iostream> #include<string> using namespace …...

浏览器主页被hao123劫持的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…...

华为OD机试题 - 热点网络统计(JavaScript)| 含代码编写思路

华为OD机试题 最近更新的博客使用说明本篇题解:热点网络统计题目输入输出描述示例一输入输出示例二输入输出Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华…...

IT项目经理的自我修养手册

在不断进步的时代&#xff0c;任何岗位职责都是一个责任、权力与义务的综合体&#xff0c;有多大的权力就应该承担多大的责任&#xff0c;有多大的权力和责任应该尽多大的义务&#xff0c;任何割裂开来的做法都会发生问题。那么作为IT项目经理的岗位职责&#xff0c;我大概列举…...

2023年软考中级电子商务设计师考什么?

首先&#xff0c;电子商务设计师属于软考中级&#xff0c;因此难度也不是特别大。但并不是说就完全没有难度&#xff0c;难度还是有的&#xff0c;像上午题一般把基本知识点掌握了&#xff0c;是没什么问题的&#xff0c;重点就在于下午题会比较难。 接下来我们来剖析一下考试…...

现在的00后太强了,几个问题差点给我问懵了

前言 我们公司刚入职一个00后小伙&#xff0c;今天在办公室交流了一下&#xff0c;他问我会不会自动化测试&#xff0c;我说懂一点&#xff0c;然后直接问了我几个自动化测试问题&#xff0c;差点直接给我问懵了&#xff01; 问题如下&#xff1a; 我们在制定自动化测试实施…...

$3 : 水​​​​​项目实战 - 水果库存系统

javase知识点复习&#xff1a; final关键字&#xff1a;http://t.csdn.cn/bvFgu 接口的定义&#xff0c;特性&#xff0c;实现&#xff0c;继承&#xff1a;http://t.csdn.cn/tbXl3 异常&#xff1a;http://t.csdn.cn/VlS0Z DAO的概念和角色&#xff08;设计理念&#xff09;&a…...

毕业设计 基于STM32单片机无线ZIGBEE智能大棚土壤湿度光照检测

基于STM32单片机无线ZIGBEE智能大棚土壤湿度光照检测1、项目简介1.1 系统构成1.2 系统功能2、部分电路设计2.1 STM32F103C8T6核心系统电路设计2.2 光敏采集电路设计2.3 温度采集电路设计3、部分代码展示3.1 读取DS18B20温度值3.2 定时器初始化1、项目简介 选题指导&#xff0c…...

华为OD机试真题Java实现【相对开音节】真题+解题思路+代码(20222023)

相对开音节 题目 相对开音节构成的结构为辅音+元音(aeiou)+辅音(r除外)+e,常见的单词有bike、cake等。 给定一个字符串,以空格为分隔符,反转每个单词中的字母,若单词中包含如数字等其他非字母时不进行反转。 反转后计算其中含有相对开音节结构的子串个数(连续的子串…...

【C++】30h速成C++从入门到精通(STL容器listvector)

listlist的介绍list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。list与…...

操作系统---存储管理

存储管理 操作系统将外存的文件调入到内存中&#xff0c;以便CPU调用&#xff0c;如果调用的内容不在内存中&#xff0c;则会产生缺页中断&#xff1b;产生缺页中断后&#xff0c;这事需要从外存调数据到内存中&#xff0c;然后CPU接着从断点继续调用内存中的数据&#xff1b;在…...

华为OD机试题 - 好朋友(JavaScript)| 含思路

华为OD机试题 最近更新的博客使用说明本篇题解:好朋友题目输入输出示例一输入输出说明示例二输入输出说明Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典...

socket本地多进程通信基本使用方法和示例

目录 前言&#xff1a; socket是什么 socket基本原理框图 socket基本函数 1 socket() 函数 2 bind()函数 3 connect()函数 4 listen() 函数 5 accept() 函数 6 read() write() send() recv()函数 7 close()函数 8 字节序转换&#xff08;hton&#xff09; 示例代码 …...

Python 算法交易实验51 Step2 Signals 信号生成

说明 不可不读书 先从经典的一些超简单信号开始 使用移动平均指标SMA(算术&#xff09; 给出了信号的产生方法&#xff0c;还有一些测算结果&#xff0c;反正看起来都是盈利的 首先使用离线方法实验一组结果&#xff0c;然后就使用ADBS来进行类似的处理。 内容 1 原理分析…...

app上架专用软著认证电子版权在主流应用商店的使用说明2023年最新版

软著认证电子版权在主流应用商店的使用说明 目录 一、 华为应用商店 二、 腾讯应用宝 三、 小米开放平台 小米应用提交&#xff1a; 小米游戏提交&#xff1a; 四、 OPPO开放平台 OPPO应用提交: OPPO游戏&#xff08;App&#xff09;提交: OPPO小游戏&#xff08;快应…...

[Mybatis2]Mapper代理开发

文章目录 问题情境 代理开发 遵循的三条原则 1.定义与SQL映射文件同名的Mapper接口&#xff0c;并且将Mapper接口和SQL映射文件放置在同一目录下 2.设置SQL映射文件的namespace属性为Mapper接口的全限定名 3.在Mapper接口中定义方法&#xff0c;方法名就是SQL映射文件中sql…...

第十一届蓝桥杯大赛青少组国赛Python真题2

第十一届蓝桥杯大赛青少组Python 真题 第二题 提示信息&#xff1a; 杨辉三角形&#xff0c;是二项式系数在三角形中的一种几何排列。中国南宋数学家杨辉在 1261 年所著的《详 解九章算法》一书有明确记载。欧洲数学家帕斯卡在 1654 年发现这一规律&#xff0c;所以又叫做帕斯卡…...

创建springboot项目文件报红

目录 一、遇到问题 二、出现这个问题的原因 三、解决办法 三种方法 四、操作步骤 一、遇到问题 创建springboot项目的时候&#xff0c;会发现一些重要文件都变成红色了&#xff0c;但是不影响程序的运行。只是看起来会有点不舒服。 二、出现这个问题的原因 因为这个spr…...

gma 地理空间绘图:(1) 绘制简单的世界地图-3.设置地图框

内容回顾 gma 地理空间绘图&#xff1a;(1) 绘制简单的世界地图-1.地图绘制与细节调整 gma 地理空间绘图&#xff1a;(1) 绘制简单的世界地图-2.设置经纬网 方法 SetFrame(FrameColor ‘black’, FrameWidth 0.6, ShowFrame True, ShowLeft True, ShowBottom True, Sho…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

4. TypeScript 类型推断与类型组合

一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式&#xff0c;自动确定它们的类型。 这一特性减少了显式类型注解的需要&#xff0c;在保持类型安全的同时简化了代码。通过分析上下文和初始值&#xff0c;TypeSc…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...