杀死僵尸进程,知道linux C中的PID

时间:2012-12-02 13:13:24

标签: c linux process zombie-process

我必须在linux C中杀死/清除一个僵尸进程。我所知道的是僵尸的PID。

我在循环中创建了一些僵尸进程:

int i = 0;
for (i; i<5; i++)
{
  system("(: & exec sleep 30) &"); // create zombie for 30 sec
}

我可以使用以下方式获取他们的PID编号:

system("ps aux | awk '{ print $8 " " $2 }' | grep -w Z");

但是如何使用PID来杀死/清理它们? 我将PID保存在变量和标准信号中:

kill(PID,9) 

甚至没有工作,因为这个过程已经死了。 有没有其他方法来实现它?请不要问我为什么我要制造僵尸以后杀死他们。事实并非如此。

5 个答案:

答案 0 :(得分:3)

“僵尸”是一个已经死亡的过程。你不能再杀了它。

“僵尸”实际上只是进程表中包含进程退出状态的条目。要摆脱它,父进程必须调用wait()来检索该信息。或者,父进程可以退出;然后,孩子成为所谓的“孤儿”并被init采用,ID为1的过程。init自动收回所有死去的孩子。

答案 1 :(得分:3)

这是我创建的用于杀死所有僵尸进程的脚本。它使用GDB调试器附加到父进程并发送waitpid来终止僵尸进程。这将让父母生活,只会杀死僵尸。

需要安装GDB调试器,您需要使用附加到进程的权限登录。这已经在Centos 6.3上进行了测试

#!/bin/bash
##################################################################
# Script: Zombie Slayer
# Author: Mitch Milner
# Date:   03/13/2013 ---> A good day to slay zombies
#
# Requirements: yum install gdb
#               permissions to attach to the parent process
#
# This script works by using a debugger to
# attach to the parent process and then issuing
# a waitpid to the dead zombie. This will not kill
# the living parent process.
##################################################################

clear
# Wait for user input to proceed, give user a chance to cancel script
echo "***********************************************************"
echo -e "This script will terminate all zombie process."
echo -e "Press [ENTER] to continue or [CTRL] + C to cancel:"
echo "***********************************************************"
read cmd_string
echo -e "\n"

# initialize variables
intcount=0
lastparentid=0

# remove old gdb command file
rm -f /tmp/zombie_slayer.txt

# create the gdb command file
echo "***********************************************************"
echo "Creating command file..."
echo "***********************************************************"
ps -e -o ppid,pid,stat,command | grep Z | sort | while read LINE; do
  intcount=$((intcount+1))
  parentid=`echo $LINE | awk '{print $1}'`
  zombieid=`echo $LINE | awk '{print $2}'`
  verifyzombie=`echo $LINE | awk '{print $3}'`

  # make sure this is a zombie file and we are not getting a Z from
  # the command field of the ps -e -o ppid,pid,stat,command
  if [ "$verifyzombie" == "Z" ]
  then
    if [ "$parentid" != "$lastparentid" ]
    then
      if [ "$lastparentid" != "0" ]
      then
        echo "detach" >> /tmp/zombie_slayer.txt
      fi
    echo "attach $parentid" >> /tmp/zombie_slayer.txt
    fi
    echo "call waitpid ($zombieid,0,0)" >> /tmp/zombie_slayer.txt
    echo "Logging: Parent: $parentid  Zombie: $zombieid"
    lastparentid=$parentid
  fi
done
if [ "$lastparentid" != "0" ]
then
  echo "detach" >> /tmp/zombie_slayer.txt
fi

# Slay the zombies with gdb and the created command file
echo -e "\n\n"
echo "***********************************************************"
echo "Slaying zombie processes..."
echo "***********************************************************"
gdb -batch -x /tmp/zombie_slayer.txt
echo -e "\n\n"
echo "***********************************************************"
echo "Script complete."
echo "***********************************************************"

享受。

答案 2 :(得分:2)

你是不对的,因为他们已经死了,你无法杀死僵尸。

他们是僵尸的原因是因为这个过程已经完成但父母没有收到退出代码。

最终,如果僵尸成为孤儿,init应该为你做这件事。一个真正的僵尸,一个仍然有父母但父母尚未收获退出代码的进程将一直持续到以下任何一个:

  • 收获退出代码;或
  • 当父母退出时,它就变成孤儿。

答案 3 :(得分:1)

你在做什么似乎很扭曲。我将假设你已经尝试创建一个最小的测试用例来展示更广泛的问题并且无论如何都要回答 - 当一个羽化过程没有清理(调用waitpid和朋友)它的子进程资源时,会创建一个僵尸。

因此,要么正确地编写父进程代码以响应SIGCHLD并调用waitpid,或者如果您无法控制父进程,正如我猜这样的情况,请终止父进程(将SIGTERM发送给父进程) )。

后者将起作用的原因是所有没有父亲的孩子都被重新作为初始(PID 1)的父母,这将执行所需的清理工作。

答案 4 :(得分:0)

您可以尝试使用SIGCHLD信号。例如,在C:

signal(SIGCHLD, handleSIGCHLD);


  void handleSIGCHLD(int signum) {
  int stat;

 /*Kills all the zombie processes*/
  while(waitpid(-1, &stat, WNOHANG) > 0);
}