[CENTOS] [Langage C] Comment créer, éviter et créer un processus zombie

【Aperçu】

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.

[Processus zombie facile]

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.

【environnement】

[vagrant@vagrant-centos65 ~]$ cat /etc/redhat-release 
CentOS release 6.5 (Final)

[Comment créer un zombie]

Tout d'abord, la source pour créer des zombies

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);
    }
}

Faites attention à faire des zombies

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]$ 

[Comment éviter les zombies]

Méthode ① Après fork (), waitpid ()

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);
    }
}
【Résultat de l'exécution】

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]$ 

Méthode ② Double fourchette

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);
    }
}
【Résultat de l'exécution】

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]$ 

Méthode ③ Utiliser sigaction

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)
{
    ;
}
【Résultat de l'exécution】
[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]$ 

[Comment faire un zombie]

Je vais vous montrer comment terminer le processus zombie créé dans zombie.c.

Les zombies ne peuvent pas être vaincus en attaquant les zombies eux-mêmes (processus enfants).

[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]$ 

Un zombie peut être vaincu en attaquant la tête du zombie (processus parent).

[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]$ 

【Livre de référence】

[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)

[Site de référence]

Comment créer un processus zombie double fork to avoid zombie process

Recommended Posts

[Langage C] Comment créer, éviter et créer un processus zombie
Essayez de créer un module Python en langage C
Comment créer et utiliser des bibliothèques statiques / dynamiques en langage C
Comment faire une traduction japonais-anglais
Comment créer un bot slack
Comment créer un package Conda
Comment créer un robot - Avancé
Comment créer une fonction récursive
Comment créer un pont virtuel
Comment créer un Dockerfile (basique)
[Blender] Comment créer un plug-in Blender
Comment créer un robot - Basic
Comment créer un fichier de configuration
[Langage C] [Linux] Essayez de créer une simple commande Linux * Ajoutez simplement! !!
Présentation de la création d'un socket serveur et de la création d'un socket client
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
Comment créer un clone depuis Github
Comment diviser et enregistrer un DataFrame
Comment créer un dossier git clone
[Python] Comment rendre une classe itérable
Comment créer un référentiel à partir d'un média
Comment créer un indicateur personnalisé Backtrader
Comment créer un plan de site Pelican
Comment diviser et traiter une trame de données à l'aide de la fonction groupby
Comment faire exécuter un thread de processus uniquement sur un cœur de processeur spécifique
Comment rendre le nom du conteneur accessible dans Docker en tant que sous-domaine
3. Traitement du langage naturel avec Python 1-2. Comment créer un corpus: Aozora Bunko
Comment créer un système de dialogue dédié aux débutants
Comment créer des variables explicatives et des fonctions objectives
Comment créer un fichier JSON en Python
Comment créer un dictionnaire avec une structure hiérarchique.
Méthode de contrôle exclusive multi-processus en langage C
Créez un chat bot et entraînez-vous à être populaire.
Comment créer un plug-in QGIS (génération de package)
J'ai lu "Comment créer un laboratoire de piratage"
[Note] Comment créer un environnement de développement Ruby
Comment créer une boîte de saisie Kivy 1 ligne
Procédure de création d'application multi-plateforme avec kivy
Comment créer une API Rest dans Django
[Note] Comment créer un environnement de développement Mac
J'ai essayé de faire un processus périodique avec CentOS7, Selenium, Python et Chrome
Comment lire les fichiers de numéros de série en boucle, les traiter et les représenter graphiquement
Langage C pour voir et se souvenir de la partie 3 Appelez le langage C depuis Python (argument) c = a + b
[Python] Comment créer un environnement de serveur Web local avec SimpleHTTPServer et CGIHTTPServer
Lire la source Python-Markdown: Comment créer un analyseur
Comment afficher la date de modification d'un fichier en langage C jusqu'à nanosecondes
Comment créer un sous-menu avec le plug-in [Blender]
[GCF + Python] Comment importer Excel vers GCS et créer une nouvelle table dans BigQuery
Comment faire un jeu de tir avec toio (partie 1)
[Go] Comment créer une erreur personnalisée pour Sentry
Comment créer une clé USB que l'installateur Linux et Win10 et winpe peuvent démarrer UEFI
Comment mettre Pyenv sur Amazon Linux et Ubuntu pour créer un environnement Python 3.6.0
Comment créer un package Python à l'aide de VS Code
Comment créer un référentiel local pour le système d'exploitation Linux
[Python] Comment créer une matrice de corrélation et une carte thermique
Bases de PyTorch (2) -Comment créer un réseau de neurones-
Comment créer un simple script serveur / client TCP