详解linux下避免僵尸进程的几种方法

linux下我们可以调用fork函数创建子进程,创建的子进程将会得到父进程的数据空间、堆、栈……副本(采用写时复制机制),子进程将会继承父进程的信号掩码、信号处理方式、当前工作目录、会话id、组id……。当子进程退出时父进程应当及时获取子进程退出状态,否则,如果父进程是一直在运行,那么子进程的退出状态将一直保存在内存中,直到父进程退出才释放。

我们可以使用如下几种方法避免僵尸进程的产生:

1.在fork后调用wait/waitpid函数取得子进程退出状态。

2.调用fork两次(第一次调用产生一个子进程,第二次调用fork是在第一个子进程中调用,同时将父进程退出(第一个子进程退出),此时的第二个子进程的父进程id为init进程id(注意:新版本Ubuntu并不是init的进程id))。

3.在程序中显示忽略SIGCHLD信号(子进程退出时会产生一个SIGCHLD信号,我们显示忽略此信号即可)。

4.捕获SIGCHLD信号并在捕获程序中调用wait/waitpid函数。

方法一:

?

#include "../common/common.h"

int main(void)

{

  pid_t pid;

 

  if ((pid = fork()) < 0) {

    perror("fork error");

    return EXIT_FAILURE;

  } else if (0 == pid) {

    printf("[%ld] child process is running...\n", (long)getpid());

    _exit(0);

  }

 

  //sleep(15);

 

  if (waitpid(pid, NULL, 0) < 0) {

    perror("waitpid error");

    return EXIT_FAILURE;

  }

 

  for (; ;) {

    pause();

  }

  return EXIT_SUCCESS;

}

方法二:

?

#include <sys/wait.h>

#include "../common/common.h"

int main(void)

{

  pid_t pid;

 

  if ((pid = fork()) < 0) {

    perror("fork error");

    return EXIT_FAILURE;

  } else if (0 == pid) {

    printf("first child is running..\n");

    /**在第一个子进程中再次fork***/

    if ((pid = fork()) < 0) {

      perror("fork error");

      return EXIT_FAILURE;

    } else if (pid > 0) {/**父进程退出**/

      printf("[%ld] first child is exit...\n", (long)getpid());

      _exit(0);

    }

 

    sleep(2);/**确保父进程先运行**/

    printf("second process pid: %ld, second process's parent pid: %ld\n", (long)getpid(), (long)getppid());

    //sleep(15);

    printf("[%ld] is exit..\n", (long)getpid());

    _exit(0);

  }

 

  /***获得第一个子进程的退出状态***/

  if (waitpid(pid, NULL, 0) < 0) {

    perror("waitpid error");

    return EXIT_FAILURE;

  }

 

  for(;;)

    pause();

  return EXIT_SUCCESS;

}

方法三:

?

#include <signal.h>

#include "../common/common.h"

int main(void)

{

  /***显示忽略SIGCHLD信号****/

  if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) {

    perror("signal error");

    return EXIT_SUCCESS;

  }

 

  pid_t pid;

  int i;

  /**产生10个子进程***/

  for (i=0; i<10; ++i) {

    if ((pid = fork()) < 0) {

      perror("fork error");

      return EXIT_FAILURE;

    } else if (0 == pid) {

      _exit(0);

    }

    sleep(2);

    continue;

  }

 

  for (; ;)

    pause();

  return EXIT_SUCCESS;

}

方法四:

?

#include <signal.h>

#include <sys/wait.h>

#include "../common/common.h"

void sig_chld(int signo);

int main(void)

{

  /**捕获此信号, 此刻系统会立刻检测是否有次信号产生**/

  if (signal(SIGCHLD, sig_chld) == SIG_ERR) {

    handler_err("signal error to SIGCHLD");

  }

 

  pid_t pid;

  int i;

  for (i=0; i<10; i++) {

 

    if ((pid = fork()) < 0) {

      handler_err("fork error");

    } else if (0 == pid) {

      printf("child pid: %d\n", getpid());

      _exit(0);

    }

 

    sleep(1);

    continue;

  }

 

  for (; ;) {

    pause();

  

  return EXIT_SUCCESS;

}

 

/**捕获到信号后会立刻执行此段代码***/

void sig_chld(int signo)

{

  printf("receive child signal\n");

  if (waitpid(-1, NULL, 0) < 0) {

    perror("waitpid error");

  }

 

  if (signal(SIGCHLD, sig_chld) == SIG_ERR) {

    perror("signal error to SIGCHLD");

  }

}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

原文链接:http://blog.csdn.net/ComingFlying/article/details/76718809

原创文章,作者:KVOMG,如若转载,请注明出处:http://www.wangzhanshi.com/n/6613.html

(0)
KVOMG的头像KVOMG
上一篇 2025年1月1日 16:23:03
下一篇 2025年1月1日 16:23:06

相关推荐

  • linux中install命令和cp命令的使用与区别

    前言 install和cp类似,都可以将文件/目录拷贝到指定的地点。但是,install允许你控制目标文件的属性。install通常用于程序的makefile(在RPM的spec里…

    Linux 2025年1月1日
  • linux日志轮询方案

    logrotate 简介 一般来说,日志是任何故障排除过程中非常重要的一部分,但这些日志会随着时间增长。在这种情况下,我们需要手动执行日志清理以回收空间,这是一件繁琐的管理任务。为…

    Linux 2024年12月17日
  • Linux磁盘格式化命令详解

    命令:mke2fs mke2fs [选项] 文件系统 磁盘盘符= 注释: 1、磁盘虽然分好区了,但是还不能用,还需要在这每一个分区上格式化,所谓格式化,其实就是安装文件系统,win…

    2025年1月1日
  • Linux PXE高效批量网络装机过程

    一、PXE概述 1.简介 PXE(Preboot eXcution Environment)预启动执行环境,是由Intel公司开发的网络引导技术,工作在Client\Server模…

    2024年12月17日
  • Linux进程地址空间详解

    一、C语言内存管理基础 引入:以前我们知道一个指针指向的如果是一个常量字符串,那么这个就是指向的常量区,只读不可被修改,因此下面的程序会崩溃。 1、在我们C语言内存管理机制里面线性…

    2024年12月17日
  • Linux系统cpu飙高的排查方法

    1.通过top命令查看cpu占比较高的进程ID 2.通过top -H -p <进程ID>命令查看该进程中具体线程,可以看到第一个线程 4311 占用了88.2%的cpu…

    2024年12月17日
  • Linux基础学习之文件查找find的常见用法

    前言 在linux的日常管理中,find的使用频率很高,熟练掌握对提高工作效率很有帮助。 find的语法比较简单,常用参数的就那么几个,比如-name、-type、-ctime等。…

    Linux 2025年1月1日
  • 干货 | Linux新手入门好书推荐

    前言 经常有读者问小编可否推荐一些 linux 入门书籍,正好最近在知乎也看到类似的问题,如几个零碎的命令难以在 linux 环境中存活,所以如果要真正形成自己的知识体系,还是要靠…

    2025年1月1日
  • 详解linux添加硬盘分区挂载教程

    基本步骤:分区——格式化——挂载——写入文件 1、首先用fdisk -l命令查看添加的硬盘名称,可以看到sdb为新增的硬盘 ? [root@oracle ~]# fdisk -l …

    Linux 2025年1月1日
  • Linux恢复删除文件的lsof命令详解

    lsof命令 lsof命令用于查看你进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。是十分方便的系统监视工具,因为lsof命令需要访问核心内…

    Linux 2025年1月1日

发表回复

登录后才能评论