Уничтожение процесса зомби, зная 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);
}