Nous fabriquerons des zombies en utilisant le virus T développé par la société pharmaceutique Umbrella. C'est une blague, et je vais vous montrer comment créer, éviter et créer un processus zombie dans C.
Un processus zombie est un processus enfant dans lequel le processus parent laisse le processus enfant seul et ne peut pas être arrêté indéfiniment.
[vagrant@vagrant-centos65 ~]$ cat /etc/redhat-release
CentOS release 6.5 (Final)
zombie.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int
main(int argc, char *argv[])
{
pid_t pid;
//Vérification des arguments
if (argc != 3) {
fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
exit(1);
}
//fork pour créer un processus enfant
//Pour le traitement après fork, deux processus, un processus parent et un processus enfant, sont exécutés en même temps.
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork(2) failed\n");
exit(1);
}
//La valeur de retour de fork du processus enfant est 0
if (pid == 0) { /*Ce que fait le processus enfant*/
execl(argv[1], argv[1], argv[2], NULL);
/* execl()Ne reviendra pas en cas de succès, donc tout échouera s'il est retourné*/
perror(argv[1]);
exit(99);
}
//La valeur de retour du fork du processus parent est l'ID de processus du processus enfant.
else { /*Ce que fait le processus parent*/
//Le temps de survie des zombies est de 30 secondes
//Je l'ai mis à 30 secondes ici, mais pendant(1)Dans le cas d'une boucle infinie comme, les zombies existeront toujours
sleep(30);
printf("child (PID=%d) finished;\n", pid);
exit(0);
}
}
Argument 1: Chemin complet de la commande à exécuter (cette fois / bin / echo
)
Argument 2: Paramètre pour la commande de l'argument 1 (cette fois This is zombie
)
Si vous exécutez comme ci-dessous, l'invite ne reviendra pas pendant 30 secondes et vous ne pourrez pas confirmer l'existence de zombies sur le même terminal. (Si vous souhaitez vérifier les zombies en élevant un autre terminal, vous pouvez utiliser la méthode suivante.)
[vagrant@vagrant-centos65 tmp]$ gcc -o zombie ./zombie.c
[vagrant@vagrant-centos65 tmp]$ ./zombie /bin/echo "This is zombie"
This is zombie //→ Il y a des effets tels que devoir attendre 30 secondes dans cet état et ne pas pouvoir effectuer d'autres travaux.
child (PID=24579) finished; //→ S'affiche après 30 secondes
[vagrant@vagrant-centos65 tmp]$
Par conséquent, ajoutez & à la fin de la commande comme indiqué ci-dessous et exécutez-le dans le processus d'arrière-plan. Nous confirmons également l'existence de zombies avec la commande ps pendant les 30 secondes où les zombies existent. Vous pouvez confirmer qu'il s'agit d'un zombie car «défunt» est affiché dans le résultat de la commande ps.
[vagrant@vagrant-centos65 tmp]$ ./zombie /bin/echo "This is zombie" &
[1] 24601
[vagrant@vagrant-centos65 tmp]$ This is zombie
//→ Si vous n'appuyez pas sur Entrée, l'invite ne sera pas renvoyée, alors appuyez sur Entrée
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ ps aux | grep defunct | grep -v grep
vagrant 24602 0.0 0.0 0 0 pts/0 Z 23:06 0:00 [echo] <defunct>
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ child (PID=24602) finished; //→ S'affiche après 30 secondes
//→ Si vous n'appuyez pas sur Entrée, l'invite ne sera pas renvoyée, alors appuyez sur Entrée
[1]+ Done ./zombie /bin/echo "This is zombie"
[vagrant@vagrant-centos65 tmp]$
Après la fourche, le processus parent utilise waitpid pour intercepter l'arrêt du processus enfant. Il est de la responsabilité des parents d'empêcher les zombies de se produire.
zombie_avoid1.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int
main(int argc, char *argv[])
{
pid_t pid;
//Vérification des arguments
if (argc != 3) {
fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
exit(1);
}
//fork pour créer un processus enfant
//Pour le traitement après fork, deux processus, un processus parent et un processus enfant, sont exécutés en même temps.
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork(2) failed\n");
exit(1);
}
//La valeur de retour de fork du processus enfant est 0
if (pid == 0) { /*Ce que fait le processus enfant*/
execl(argv[1], argv[1], argv[2], NULL);
/* execl()Ne reviendra pas en cas de succès, donc tout échouera s'il est retourné*/
perror(argv[1]);
exit(99);
}
//La valeur de retour du fork du processus parent est l'ID de processus du processus enfant.
else { /*Ce que fait le processus parent*/
int status;
waitpid(pid, &status, 0);
sleep(30);
printf("child (PID=%d) finished; ", pid);
if (WIFEXITED(status))
printf("exit, status=%d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("signal, sig=%d\n", WTERMSIG(status));
else
printf("abnormal exit\n");
exit(0);
}
}
Vous pouvez confirmer que le zombie n'existe pas avec la commande ps.
[vagrant@vagrant-centos65 tmp]$ gcc -o zombie_avoid1 ./zombie_avoid1.c
[vagrant@vagrant-centos65 tmp]$ ./zombie_avoid1 /bin/echo "This is zombie" &
[1] 24619
[vagrant@vagrant-centos65 tmp]$ This is zombie
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ ps aux | grep defunct | grep -v grep
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ child (PID=24620) finished; exit, status=0
[1]+ Done ./zombie_avoid1 /bin/echo "This is zombie"
[vagrant@vagrant-centos65 tmp]$
Créez un processus enfant à partir d'un processus parent et un processus petit-enfant à partir d'un processus enfant. Et en mettant fin au processus enfant, le processus petit-enfant ne devient pas un zombie car le processus parent du processus petit-enfant n'existe plus. Assurez-vous que le processus petit-enfant existe toujours lorsque les processus parent et enfant se terminent.
processus | processusの終了時間 |
---|---|
Processus parent | Terminer après 30 secondes |
Processus enfant | Fin immédiate |
Processus petit-enfant | Terminer après 60 secondes |
zombie_avoid2.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int
main(int argc, char *argv[])
{
pid_t pid;
//Vérification des arguments
if (argc != 3) {
fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
exit(1);
}
//fork pour créer un processus enfant
//Pour le traitement après fork, deux processus, un processus parent et un processus enfant, sont exécutés en même temps.
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork(2) failed\n");
exit(1);
}
//La valeur de retour de fork du processus enfant est 0
if (pid == 0) { /*Ce que fait le processus enfant*/
pid_t pid_child;
pid_child = fork();
if (pid_child < 0) {
fprintf(stderr, "child fork(2) failed\n");
exit(1);
}
if (pid_child == 0) { /*Ce que fait le processus des petits-enfants*/
execl(argv[1], argv[1], argv[2], NULL);
/* execl()Ne reviendra pas en cas de succès, donc tout échouera s'il est retourné*/
perror(argv[1]);
exit(99);
} else { /*Ce que fait le processus enfant*/
printf("grandchild (PID=%d) finished; ", pid_child);
exit(0);
}
}
//La valeur de retour du fork du processus parent est l'ID de processus du processus enfant.
else { /*Ce que fait le processus parent*/
int status;
waitpid(pid, &status, 0);
sleep(30);
printf("child (PID=%d) finished; ", pid);
if (WIFEXITED(status))
printf("exit, status=%d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("signal, sig=%d\n", WTERMSIG(status));
else
printf("abnormal exit\n");
exit(0);
}
}
Cette fois, j'utilise sleep
au lieu de ʻecho` pour vérifier l'existence d'un processus petit-enfant.
[vagrant@vagrant-centos65 tmp]$ gcc -o zombie_avoid2 ./zombie_avoid2.c
[vagrant@vagrant-centos65 tmp]$ ./zombie_avoid2 /bin/sleep 60 &
[1] 25674
[vagrant@vagrant-centos65 tmp]$ grandchild (PID=25676) finished;
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$
//Les zombies n'existent pas
[vagrant@vagrant-centos65 tmp]$ ps aux | grep defunct | grep -v grep
//Le processus des petits-enfants existe
[vagrant@vagrant-centos65 tmp]$ ps aux | grep 25676 | grep -v grep
vagrant 25676 0.0 0.1 100924 620 pts/0 S 01:29 0:00 /bin/sleep 60
[vagrant@vagrant-centos65 tmp]$ child (PID=25675) finished; exit, status=0
[1]+ Done ./zombie_avoid2 /bin/sleep 60
[vagrant@vagrant-centos65 tmp]$
//Le processus petit-enfant existe toujours même si le processus parent se termine
[vagrant@vagrant-centos65 tmp]$ ps aux | grep 25676 | grep -v grep
vagrant 25676 0.0 0.1 100924 620 pts/0 S 01:29 0:00 /bin/sleep 60
[vagrant@vagrant-centos65 tmp]$
//Le processus des petits-enfants se termine également après 60 secondes
[vagrant@vagrant-centos65 tmp]$ ps aux | grep 25676 | grep -v grep
[vagrant@vagrant-centos65 tmp]$
zombie_avoid3.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <errno.h>
static void detach_children(void);
static void noop_handler(int sig);
int
main(int argc, char *argv[])
{
pid_t pid;
//Vérification des arguments
if (argc != 3) {
fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
exit(1);
}
detach_children();
//fork pour créer un processus enfant
//Pour le traitement après fork, deux processus, un processus parent et un processus enfant, sont exécutés en même temps.
pid = fork();
if (pid < 0) {
fprintf(stderr, "fork(2) failed\n");
exit(1);
}
//La valeur de retour de fork du processus enfant est 0
if (pid == 0) { /*Ce que fait le processus enfant*/
execl(argv[1], argv[1], argv[2], NULL);
/* execl()Ne reviendra pas en cas de succès, donc tout échouera s'il est retourné*/
perror(argv[1]);
exit(99);
}
//La valeur de retour du fork du processus parent est l'ID de processus du processus enfant.
else { /*Ce que fait le processus parent*/
printf("child (PID=%d) finished;\n", pid);
//Puisque le signal est capturé pendant le sommeil, il boucle indéfiniment
while(1);
exit(0);
}
}
static void
detach_children(void)
{
struct sigaction act;
act.sa_handler = noop_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART | SA_NOCLDWAIT;
if (sigaction(SIGCHLD, &act, NULL) < 0) {
printf("sigaction() failed: %s", strerror(errno));
}
}
static void
noop_handler(int sig)
{
;
}
[vagrant@vagrant-centos65 tmp]$ gcc -o zombie_avoid3 ./zombie_avoid3.c
[vagrant@vagrant-centos65 tmp]$ ./zombie_avoid3 /bin/echo "This is zombie" &
[1] 25895
[vagrant@vagrant-centos65 tmp]$ child (PID=25896) finished;
This is zombie
[vagrant@vagrant-centos65 tmp]$
//Les zombies n'existent pas
[vagrant@vagrant-centos65 tmp]$ ps aux | grep defunct | grep -v grep
// zombie_Le processus avoid3 existe
[vagrant@vagrant-centos65 tmp]$ ps aux | grep zombie_avoid3 | grep -v grep
vagrant 25895 102 0.0 3924 448 pts/0 R 02:42 0:13 ./zombie_avoid3 /bin/echo This is zombie
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ kill 25895
[vagrant@vagrant-centos65 tmp]$
[1]+ Terminated ./zombie_avoid3 /bin/echo "This is zombie"
[vagrant@vagrant-centos65 tmp]$
Je vais vous montrer comment terminer le processus zombie créé dans zombie.c
.
[vagrant@vagrant-centos65 tmp]$ ./zombie /bin/echo "This is zombie" &
[1] 25932
[vagrant@vagrant-centos65 tmp]$ This is zombie
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ ps aux | grep -e zombie -e defunct | grep -v grep
vagrant 25932 0.0 0.0 3920 372 pts/0 S 02:47 0:00 ./zombie /bin/echo This is zombie
vagrant 25933 0.0 0.0 0 0 pts/0 Z 02:47 0:00 [echo] <defunct>
[vagrant@vagrant-centos65 tmp]$
//Tuer des zombies
[vagrant@vagrant-centos65 tmp]$ kill 25933
//J'ai tué un zombie, mais le zombie existe
[vagrant@vagrant-centos65 tmp]$ ps aux | grep -e zombie -e defunct | grep -v grep
vagrant 25932 0.0 0.0 3920 372 pts/0 S 02:47 0:00 ./zombie /bin/echo This is zombie
vagrant 25933 0.0 0.0 0 0 pts/0 Z 02:47 0:00 [echo] <defunct>
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ child (PID=25933) finished;
[1]+ Done ./zombie /bin/echo "This is zombie"
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ ./zombie /bin/echo "This is zombie" &
[1] 25965
[vagrant@vagrant-centos65 tmp]$ This is zombie
[vagrant@vagrant-centos65 tmp]$
[vagrant@vagrant-centos65 tmp]$ ps aux | grep -e zombie -e defunct | grep -v grep
vagrant 25965 0.0 0.0 3920 372 pts/0 S 02:50 0:00 ./zombie /bin/echo This is zombie
vagrant 25966 0.0 0.0 0 0 pts/0 Z 02:50 0:00 [echo] <defunct>
[vagrant@vagrant-centos65 tmp]$
//Tuez le processus parent
[vagrant@vagrant-centos65 tmp]$ kill 25965
[vagrant@vagrant-centos65 tmp]$
[1]+ Terminated ./zombie /bin/echo "This is zombie"
[vagrant@vagrant-centos65 tmp]$
//Il n'y a pas de processus parents ni de zombies
[vagrant@vagrant-centos65 tmp]$ ps aux | grep -e zombie -e defunct | grep -v grep
[vagrant@vagrant-centos65 tmp]$
kill
.[Programmation Linux normale 2ème édition: La voie royale de la programmation gcc qui peut être apprise du mécanisme de Linux](https://www.amazon.co.jp/%E3%81%B5%E3%81%A4%E3%81%86% E3% 81% AELinux% E3% 83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% 9F% E3% 83% B3% E3% 82% B0-% E7 % AC% AC2% E7% 89% 88-Linux% E3% 81% AE% E4% BB% 95% E7% B5% 84% E3% 81% BF% E3% 81% 8B% E3% 82% 89% E5 % AD% A6% E3% 81% B9% E3% 82% 8Bgcc% E3% 83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% 9F% E3% 83 % B3% E3% 82% B0% E3% 81% AE% E7% 8E% 8B% E9% 81% 93-% E9% 9D% 92% E6% 9C% A8-% E5% B3% B0% E9% 83 % 8E-ebook / dp / B075ST51Y5)
Comment créer un processus zombie double fork to avoid zombie process
Recommended Posts