wait WNOHANG 僵尸进程

2023-11-05

什么是僵尸进程?
首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打开的文件等,但内核为每一个终止子进程保存了一定量的信息。这些信息至少包括进程ID,进程的终止状态,以及该进程使用的CPU时间,所以当终止子进程的父进程调用wait或waitpid时就可以得到这些信息。
而僵尸进程就是指:一个进程执行了exit系统调用退出,而其父进程并没有为它收尸(调用wait或waitpid来获得它的结束状态)的进程。
任何一个子进程(init除外)在exit后并非马上就消失,而是留下一个称外僵尸进程的数据结构,等待父进程处理。这是每个子进程都必需经历的阶段。另外子进程退出的时候会向其父进程发送一个SIGCHLD信号。
如何避免僵尸进程
通过signal(SIGCHLD, SIG_IGN)通知内核对子进程的结束不关心,由内核回收
父进程调用wait/waitpid等函数等待子进程结束,如果尚无子进程退出wait会导致父进程阻塞。waitpid可以通过传递WNOHANG使父进程不阻塞立即返回。
如果父进程很忙可以用signal注册信号处理函数,在信号处理函数调用wait/waitpid等待子进程退出。
通过两次调用fork。父进程首先调用fork创建一个子进程然后waitpid等待子进程退出,子进程再fork一个孙进程后退出。这样子进程退出后会被父进程等待回收,而对于孙子进程其父进程已经退出所以孙进程成为一个孤儿进程,孤儿进程由init进程接管,孙进程结束后,init会等待回收。
如以下代码会创建100个子进程,但是父进程并未等待它们结束,所以在父进程退出前会有100个僵尸进程。
C
#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来等待子进程返回。
C
#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;
}
但是通过运行程序发现还是会有僵尸进程,而且每次僵尸进程的数量都不定。这是为什么呢?其实主要是因为Linux的信号机制是不排队的,假如在某一时间段多个子进程退出后都会发出SIGCHLD信号,但父进程来不及一个一个地响应,所以最后父进程实际上只执行了一次信号处理函数。但执行一次信号处理函数只等待一个子进程退出,所以最后会有一些子进程依然是僵尸进程。
虽然这样但是有一点是明了的,就是收到SIGCHLD必然有子进程退出,而我们可以在信号处理函数里循环调用waitpid函数来等待所有的退出的子进程。至于为什么不用wait,主要原因是在wait在清理完所有僵尸进程后再次等待会阻塞。
所以最佳方案(个人观点)如下:
C
#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;
  while(waitpid(-1, &status, WNOHANG) > 0);
}
 
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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

wait WNOHANG 僵尸进程 的相关文章

  • 在哪里可以找到所有 C 标准库的源代码?

    我正在寻找所有 C 标准库的完整源代码 也就是说 我正在寻找 stdio h stdlib h string h math h 等的源代码 我想看看它们是如何创建的 我认为这取决于不同的平台 但 Linux 或 Windows 都会受到欢迎
  • Linux shell 标题大小写

    我正在编写一个 shell 脚本并有一个如下所示的变量 something that is hyphenated 我需要在脚本中的各个点使用它 如下所示 something that is hyphenated somethingthati
  • 有没有办法改变vim的默认模式

    有谁知道如何更改vim的默认模式 它的默认模式是命令模式 但是我可以将其更改为插入模式吗 只需将以下行添加到您的 vimrc 中 start Vim s default mode will be changed to Insert mode
  • 检查 Linux 中给定进程的打开 FD 限制

    我最近有一个 Linux 进程 泄露 了文件描述符 它打开了文件描述符 但没有正确关闭其中一些文件描述符 如果我对此进行监控 我就可以提前得知该过程已达到其极限 有没有一种很好的 Bash 或 Python 方法来检查 Ubuntu Lin
  • mod_perl 无法看到 /tmp 中的文件

    我有一些 mod perl 代码试图访问 tmp 下的文件 但它抛出 没有这样的文件或目录 错误 我在代码中添加了一个 ls al tmp 来查看 Perl 在目录中看到的内容 它只给了我 和 drwxrwxrwt 2 root root
  • 并发 I/O - 缓冲区损坏、块设备驱动程序

    我开发块分层设备驱动程序 所以 我拦截WRITE请求并加密数据 并解密数据end bio 例行程序 在处理和READ要求 所以在单流中一切正常 但是 如果尝试同时从两个或更多进程执行 I O 我会遇到缓冲区内容损坏的情况 我没有任何本地存储
  • Mongo:无法连接到服务器 127.0.0.1:27017 位于 src/mongo/shell/mongo.js:145

    当我尝试在 ubuntu 中的 shell 中运行 mongo 或打开 rockmongo 时 我看到以下错误 couldn t connect to server 127 0 0 1 27017 at src mongo shell mo
  • Git - 致命:无法获取当前工作目录?

    When I git clone从回购协议中 我得到 fatal Could not get current working directory No such file or directory 我该怎么办 我检查了服务器并发现 git文
  • Pthread互斥锁由不同线程解锁

    一个天真的问题 我之前读到过 MUTEX 只能由锁定它的线程解锁 但我写了一个程序THREAD1锁定 mutexVar 并进入睡眠状态 然后THREAD2可以直接解锁mutexVar做一些操作并返回 gt 我知道每个人都说我为什么要这样做
  • 导出多个 LD_LIBRARY_PATH 的正确方法

    对于linux的使用 我是一个新手 根据有关我的项目的指南 我必须多次导出 LD LIBRARY PATH 并且我不确定是否不覆盖它们 Cupti Tensorflow CUDAit export LD LIBRARY PATH LD LI
  • 如何像C99一样使用make和编译?

    我正在尝试使用 Makefile 编译 Linux 内核模块 obj m main o all make C lib modules shell uname r build M PWD modules clean make C lib mo
  • 容器上的“container_memory_working_set_bytes”指标和 OOM-killer 之间有什么关系?

    我试图找出并理解 OOM killer 如何在容器上工作 为了弄清楚这一点 我读了很多文章 发现 OOM killer 会根据oom score And oom score是由oom score adj以及该进程的内存使用情况 有两个指标c
  • 在 Bash 中使用“$RANDOM”生成随机字符串

    我正在尝试使用 Bash 变量 RANDOM创建一个由包含整数和字母数字的变量中的 8 个字符组成的随机字符串 例如 var abcd1234ABCD 我怎样才能做到这一点 使用参数扩展 chars 是可能的字符数 是模运算符 chars
  • 如何在 .zip 文件中使用 grep

    有 3 个文件 a csv b csv c csv 压缩为 abh zip 现在可以在 abh zip 上执行 grep 命令 是否有任何通配符 仅对里面的 c csv 文件运行 grep压缩 如果你有zipgrep 据我所知 它是随zip
  • 如何在Linux中获取带有图标的活动应用程序

    我想找到一种方法获取活动应用程序的列表及其名称和图标 实际上 我正在使用此命令来获取所有活动进程 wmctrl lp 示例输出 0x03800002 0 3293 user notebook XdndCollectionWindowImp
  • 仅为我自己禁用和重新启用地址空间布局随机化

    我想在我的系统 Ubuntu Gnu Linux 2 6 32 41 server 上禁用地址空间布局随机化 ASLR 但是 如果我使用 sysctl w kernel randomize va space 0 我认为这一更改将影响系统上的
  • 64位版本的adb和fastboot?

    我在 Debian 7 3 x64 已完全修补 上发现了以下错误 我很确定这是因为adb即使在其 SDK 工具的 64 位发行版中也是 32 位 which adb opt android sdk platform tools adb op
  • 是否可以为我的 Linux 函数复制命令的制表符补全?

    假设我有一个名为的 bash shell 函数magic 我想定义一个制表符补全功能 magic这将允许magic搭载任何给定命令的选项卡完成功能 如果可用 换句话说 我想要magic能够做这样的事情 magic git
  • 主动\被动模式下 FTP 服务器的适当 iptables 规则

    我在 CentOS6 上安装了 ProFTPD 服务器 如果我使 ftp 本地主机 我可以正确连接 但如果我从外部尝试 我会收到消息 没有到主机的路由 但有一条到主机的路由 因为我是通过 SSH 连接的 我尝试添加以下 iptable 规则
  • 如何使用 sed 交换两行?

    有谁知道如何更换line a with line b and line b with line a使用 sed 编辑器在文本文件中 我可以看到如何用保留空间中的一行替换模式空间中的一行 即 Paco x or Paco g 但是如果我想采取

随机推荐

  • Linux文件下I/O基础详解

    视频地址 华清远见 https www bilibili com video BV1dz411B7vj p 1 文件基础 一组相关数据的有序集合 文件类型 常规文件 r 二进制文件 ASCII码文件 目录文件 d 字符设备文件 c 块设备文
  • Python->进程-线程->TCP服务器客户端-服务端->返回固定数据的静态web服务器-学习

    作者 芝士小熊饼干 系列专栏 Python 坚持天数 12天 获取进程id和进程的父id 进程名 导入包 import multiprocessing import time import os 创建任务 def task1 print f
  • Django-admin录入中文错误:Incorrect string value

    在Django自带后台中经常会出现编码错误 Incorrect string value xE7 xAE x80 xE5 x8D x95 for column message at row 1 需要修改admin表的中的编码 才能保证数据正
  • Rust- FFI (Foreign Function Interface)

    Foreign Function Interface FFI is a mechanism that allows code written in one language to call code written in another l
  • 手写ArrayStack底层 实现代码

    一 接口的定义 package p1 接口 public interface Stack
  • 华为OD机试真题B卷 Java 实现【统计字符】,附详细解题思路

    一 题目描述 输入一行字符 分别统计出包含英文字母 空格 数字和其它字符的个数 数据范围 输入的字符串长度满足 1 le n le 1000 1 n 1000 二 输入描述 输入一行字符串 可以有空格 三 输出描述 统计其中英文字符 空格字
  • ECharts画动态仪表盘+柱状图(ajax获取+循环画图)

    出来工作几个月了 整理下最近学的的东西 刚刚才开通博客 第一篇就先画仪表盘 柱状图 有什么写的不好的地方 请大家多多指教 jsp中首先要引用几个文件 xx xxx js 是我js代码存放的文件
  • C++标准库异常类

    C 标准库异常类继承层次中的根类为exception 其定义在exception头文件中 它是C 标准库所有函数抛出异常的基类 exception的接口定义如下 namespace std class exception public ex
  • 记一个复制黏贴的功能想法(黏贴剪切板中的数字自增,复制黏贴自增)

    起因 照例是要写起因的 起因非常之简单 不知道大家有没有遇到过需要输入连续的 id 101 id 110 这类数字的时候 这个时候能做的基本上是复制100 黏贴100 然后手动改 101 102 在我的脑海里 除了使用excel 其他没有很
  • 【华为机试真题 JAVA】执行时长-100

    编程题目 100分 执行时长 2021 2022 Q2考试题 时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 本题可使用本地IDE编码 不能使用本地已
  • 面对对象--结构体和类的区别

    一 面向对象 结构体和类的区别 结构体是一种值类型 而类是引用类型 值类型用于存储数据的值 引用类型用于存储对实际数据的引用 那么结构体就是当成值来使用的 类则通过引用来对实际数据操作 构使用栈存储 Stack Allocation 而类使
  • 利用腾讯云函数隐藏C2服务器

    1 简介 腾讯云函数 可以为企业和开发者提供无服务器执行环境 无需购买和管理服务器 只需要在腾讯云上使用平台支持的语言编写核心代码并设置代码运行的条件 即可在腾讯云基础设施上弹性 安全地运行代码 C2服务器所有流量通过腾讯云函数进行转发 由
  • Html04_input框中的value/key/placeholder到底是什么

    1 input框中的value值到底是什么 value 属性为 input 元素设定值 input标签有很多类型 也就是type 对于不同的输入类型 value 属性的用法也不同 以下是一些常用type的说明 text 文本框 input默
  • 513. Find Bottom Left Tree Value

    Given a binary tree find the leftmost value in the last row of the tree Example 1 Input 2 1 3 Output 1 Example 2 Input 1
  • Flutter:自定义组件的上下左右弹出层

    背景 最近要使用Flutter实现一个下拉菜单 需求就是 在当前组件下点击 其下方弹出一个菜单选项 如下图所示 实现起来 貌似没什么障碍 在Flutter中本身就提供了弹出层PopupMenuButton组件和showMenu方法 于是开搞
  • 复习之linux存储的基本管理

    一 实验环境的设定 1 实验环境的搭建 本节内容只需要一台虚拟机 westosa reset重置虚拟机 保证实验环境的纯净 配置网络实现ssh连接 重置虚拟机后 配置网络 设定ip 172 25 254 100 保证与主机可以通信 实现ss
  • Ant Design的layout布局 --- 根据路由配置渲染

  • python基础3——流程控制

    文章目录 一 操作符 1 1 比较操作符 1 2 逻辑操作符 1 3 成员操作符 1 4 身份操作符 二 流程控制 2 1 条件判断 2 2 循环语句 2 2 1 for循环 2 2 2 while循环 2 3 continue与break
  • 谷歌Colab云端部署Stable Diffusion 进行绘图

    系列文章目录 本地部署Stable Diffusion教程 亲测可以安装成功 Stable Diffusion界面参数及模型使用 文章目录 系列文章目录 前言 一 Colab是什么 二 操作步骤 1 找到对应的脚本 2 在谷歌Colab里执
  • wait WNOHANG 僵尸进程

    什么是僵尸进程 首先内核会释放终止进程 调用了exit系统调用 所使用的所有存储区 关闭所有打开的文件等 但内核为每一个终止子进程保存了一定量的信息 这些信息至少包括进程ID 进程的终止状态 以及该进程使用的CPU时间 所以当终止子进程的父