obiectiv: analizați modul în care sunt create procesele zombie sau procesele defuncte și cum să le eliminați din tabelul de proces.
un proces zombie sau un proces defunct este un proces care a finalizat execuția, dar are încă o intrare în tabelul de proces. Acest lucru se întâmplă pentru procesele copil care a fost bifurcat de un proces părinte folosind apelul de sistem fork()
, dar nu a fost cules de procesul părinte folosind apelul de sistem wait()
.
procesul părinte trebuie să efectueze un apel de sistem wait()
(sau waitpid()
) pentru a obține starea de ieșire a procesului copil odată ce procesul copil s-a încheiat. Dacă apelul wait()
nu este efectuat de procesul părinte, procesul copil va deveni un proces zombie.
un semnal SIGCHLD
este trimis la procesul părinte ori de câte ori un proces copil se termină. Procesul părinte trebuie să aibă o funcție de manipulare a semnalului SIGCHLD
definită cu un apel la wait()
– aceasta va elimina procesul copil din tabelul de proces.
pentru a elimina procesele zombie dintr-un sistem, semnalul SIGCHLD
poate fi trimis manual părintelui, folosind comanda kill
. Dacă procesul părinte încă refuză să culeagă procesul zombie și dacă procesul părinte poate fi ucis, următorul pas este să ucizi procesul părinte. Când un proces copil își pierde procesul părinte, init
(PID 1) devine noul său părinte. init
execută periodic apelul de sistem wait()
pentru a culege orice proces zombie cu init
ca părinte.
am scris un program simplu C pentru a crea un proces 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/tipuri.h>
#includeți < sys/așteptați.h>
#include < unistd.h>
#includeți < errno.h >
int principal ()
{
pid_t child_pid;
int child_status;
child_pid = furculiță ();
dacă (child_pid > 0) {
// procesul părinte va dormi timp de 30 de secunde și de ieșire, fără un apel să aștepte()
fprintf (stderr, „procesul părinte – %d \ n”, getpid());
somn(30);
ieșire(0);
}
altfel dacă (child_pid == 0) {
// procesul copil va ieși imediat
fprintf (stderr, „procesul copil – %d \ n”, getpid());
ieșire(0);
}
altfel dacă (child_pid == -1) {
// fork () eroare
perror („fork() apel eșuat”);
ieșire (-1);
}
altfel {
// acest lucru nu ar trebui să se întâmple
fprintf (stderr, „valoarea returnată necunoscută a %D de la fork() call”, child_pid);
ieșire (-2);
}
întoarcere 0;
}
|
salvați codul de mai sus ca zombie.c
și compilați-l folosind gcc
.
$ gcc zombie.c -o zombie
apoi, rulați programul.
$ ./zombie parent process - 26570child process - 26571
de la un alt terminal, efectuați o ps
pentru a afișa procesele în execuție. Veți vedea un 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>
odată ce procesul părinte s-a încheiat (după 30 de secunde), procesul zombie va fi eliminat din tabelul de proces prin procesul init
.
Mohamed Ibrahim
ibrahim = { interested_in (Unix, linux, android, open_source, reverse_engineering); codificare(C, shell, php, python, java, javascript, nodejs, react); plays_on(xbox, ps4); linux_desktop_user(adevărat); }