Уничтожение процесса зомби, зная PID в Linux C

Я должен убить / очистить процесс зомби в 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 ответов

Решение

Вот скрипт, который я создал, чтобы убить ВСЕ процессы зомби. Он использует отладчик 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 "***********************************************************"

Наслаждаться.

"Зомби" - это процесс, который уже мертв. Вы не можете убить это снова.

"Зомби" - это на самом деле просто запись в таблице процессов, содержащая статус выхода процесса. Чтобы избавиться от этого, родительский процесс должен вызвать wait() чтобы получить эту информацию. В качестве альтернативы родительский процесс может выйти сам; тогда ребенок становится так называемым "сиротой" и становится усыновленным init, процесс с ID 1. init автоматически пожинает всех мертвых детей.

Вы правы, что вы не можете убивать зомби, потому что они уже мертвы.

Причина, по которой они зомби, заключается в том, что процесс завершен, но родитель не собрал код выхода.

В конце концов, init должен сделать это для вас, если и когда зомби станет сиротой. Настоящий зомби, процесс, у которого все еще есть родитель, но этот родитель еще не собрал код выхода, будет существовать до тех пор, пока:

  • родитель собирает код выхода; или же
  • он становится сиротой, когда родитель выходит.

То, что ты делаешь, кажется довольно искаженным. Я собираюсь предположить, что вы пытались создать минимальный тестовый пример, чтобы показать более широкую проблему и ответить в любом случае - зомби создается, когда перьевой процесс не очищает (вызывает waitpid и друзей) ресурсы своего дочернего процесса.

Итак, либо правильно напишите код родительского процесса, чтобы он отвечал на SIGCHLD и вызывал waitpid, либо, если у вас нет контроля над родительским процессом, как я полагаю, в этом случае, убейте родительский процесс (отправьте SIGTERM отцу).

Причина того, что последний сработает, заключается в том, что все дети без отца переизбираются на init (PID 1), который проведет необходимую очистку.

Вы можете попробовать использовать сигнал SIGCHLD. Например, в C:

signal(SIGCHLD, handleSIGCHLD);


  void handleSIGCHLD(int signum) {
  int stat;

 /*Kills all the zombie processes*/
  while(waitpid(-1, &stat, WNOHANG) > 0);
}
Другие вопросы по тегам