cel: analiza sposobu tworzenia procesów zombie lub procesów nieistniejących i jak je usunąć z tabeli procesów.
proces zombie lub proces nieistniejący to proces, który zakończył wykonywanie, ale nadal ma wpis w tabeli procesów. Ma to miejsce w przypadku procesów potomnych, które zostały rozwidlone przez proces nadrzędny korzystający z wywołania systemowego fork()
, ale nie są pobierane przez proces nadrzędny korzystający z wywołania systemowego wait()
.
proces nadrzędny musi wykonać wywołanie systemowe wait()
(lub waitpid()
), aby uzyskać status zakończenia procesu potomnego po zakończeniu procesu potomnego. Jeśli wywołanie wait()
nie zostanie wykonane przez proces macierzysty, proces potomny stanie się procesem zombie.
sygnał SIGCHLD
jest wysyłany do procesu nadrzędnego za każdym razem, gdy proces potomny zakończy działanie. Proces nadrzędny musi mieć funkcję obsługi sygnału SIGCHLD
zdefiniowaną przez wywołanie
aby usunąć procesy zombie z systemu, sygnał SIGCHLD
może być wysłany do rodzica ręcznie, za pomocą polecenia kill
. Jeśli proces macierzysty nadal odmawia pobierania procesu zombie i jeśli proces macierzysty może zostać zabity, następnym krokiem jest zabicie procesu macierzystego. Gdy proces potomny straci swój proces nadrzędny, init
(PID 1) staje się jego nowym rodzicem. init
okresowo wykonuje wywołanie systemowe wait()
, aby zebrać wszystkie procesy zombie z init
jako rodzicem.
napisałem prosty program C do tworzenia procesu zombie.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include < sys / wait.h>
#include < unistd.h>
#include < errno.h>
int main ()
{
pid_t child_pid;
int child_status;
child_pid = fork ();
if (child_pid > 0) {
// proces macierzysty zostanie uśpiony na 30 sekund i zakończy działanie bez wywołania wait()
fprintf(stderr, „parent process – %d\n”, getpid());
sen(30);
wyjście(0);
}
else if (child_pid == 0) {
// proces potomny natychmiast zakończy działanie
fprintf (stderr,” proces potomny – %d\n”, getpid());
wyjście(0);
}
else if (child_pid == -1) {
// błąd fork ()
perror („wywołanie fork() nie powiodło się”);
wyjście (-1);
}
else {
// to nie powinno się zdarzyć
fprintf (stderr, „unknown return value of % d from fork() call”, child_pid);
exit (-2);
}
return 0;
}
|
Zapisz powyższy kod jako zombie.c
i skompiluj go za pomocą gcc
.
$ gcc zombie.c -o zombie
następnie uruchom program.
$ ./zombie parent process - 26570child process - 26571
z innego terminala wykonaj ps
, aby wyświetlić uruchomione procesy. Zobaczysz proces zombie.
$ ps -ef | grep zombieibrahim 26570 22886 0 15:59 pts/2 00:00:00 ./zombieibrahim 26571 26570 0 15:59 pts/2 00:00:00 <defunct>
po zakończeniu procesu nadrzędnego (po 30 sekundach) proces zombie zostanie usunięty z tabeli procesów przez proces init
.
Mohamed Ibrahim
ibrahim = { interested_in(unix, linux, android, open_source, reverse_engineering); coding(C, shell, php, python, java, javascript, NodeJS, react); plays_on(xbox, ps4); linux_desktop_user(true); }