[LINUX] [C-Sprache] So erstellen, vermeiden und erstellen Sie einen Zombie-Prozess

【Überblick】

Wir werden Zombies mit dem vom Pharmaunternehmen Umbrella entwickelten T-Virus herstellen. Das ist ein Witz, und ich zeige Ihnen, wie Sie in C einen Zombie-Prozess erstellen, vermeiden und ausführen.

[Einfacher Zombie-Prozess]

Ein Zombie-Prozess ist ein untergeordneter Prozess, bei dem der übergeordnete Prozess den untergeordneten Prozess in Ruhe lässt und nicht auf unbestimmte Zeit beendet werden kann.

【Umgebung】

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

[Wie erstelle ich einen Zombie]

Erstens die Quelle für die Erstellung von 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;

    //Argumentprüfung
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
        exit(1);
    }

    //Gabel, um einen untergeordneten Prozess zu erstellen
    //Für die Verarbeitung nach dem Verzweigen werden zwei Prozesse gleichzeitig ausgeführt, ein übergeordneter Prozess und ein untergeordneter Prozess.
    pid = fork();
    if (pid < 0) {
        fprintf(stderr, "fork(2) failed\n");
        exit(1);
    }

    //Der Rückgabewert von fork des untergeordneten Prozesses ist 0
    if (pid == 0) { /*Was der untergeordnete Prozess tut*/
        execl(argv[1], argv[1], argv[2], NULL);
        /* execl()Wird bei Erfolg nicht zurückgegeben, daher schlägt bei Rückgabe alles fehl*/
        perror(argv[1]);
        exit(99);
    }
    //Der Rückgabewert der Verzweigung des übergeordneten Prozesses ist die Prozess-ID des untergeordneten Prozesses.
    else {          /*Was der übergeordnete Prozess tut*/
        //Die Überlebenszeit der Zombies beträgt 30 Sekunden
        //Ich habe es hier auf 30 Sekunden eingestellt, aber während(1)Im Falle einer Endlosschleife wie gibt es immer Zombies
        sleep(30);
        printf("child (PID=%d) finished;\n", pid);
        exit(0);
    }
}

Sei vorsichtig, wie man Zombies macht

Argument 1: Vollständiger Pfad des auszuführenden Befehls (diesmal / bin / echo) Argument 2: Parameter für den Befehl von Argument 1 (diesmal This is zombie)

Wenn Sie wie folgt ausführen, wird die Eingabeaufforderung 30 Sekunden lang nicht zurückgegeben, und Sie können die Existenz von Zombies auf demselben Terminal nicht bestätigen. (Wenn Sie die Zombies überprüfen möchten, indem Sie ein anderes Terminal anheben, können Sie die folgende Methode verwenden.)

[vagrant@vagrant-centos65 tmp]$ gcc -o zombie ./zombie.c 
[vagrant@vagrant-centos65 tmp]$ ./zombie /bin/echo "This is zombie"
This is zombie //→ Es gibt Effekte wie das Warten von 30 Sekunden in diesem Zustand und die Unfähigkeit, andere Arbeiten auszuführen.
child (PID=24579) finished; //→ Wird nach 30 Sekunden angezeigt
[vagrant@vagrant-centos65 tmp]$ 

Fügen Sie daher & am Ende des Befehls wie unten gezeigt hinzu und führen Sie ihn im Hintergrund aus. Wir bestätigen auch die Existenz von Zombies mit dem Befehl ps während der 30 Sekunden, in denen Zombies existieren. Sie können bestätigen, dass es sich um einen Zombie handelt, da im Ergebnis des Befehls ps "defunct" angezeigt wird.

[vagrant@vagrant-centos65 tmp]$ ./zombie /bin/echo "This is zombie" &
[1] 24601
[vagrant@vagrant-centos65 tmp]$ This is zombie
//→ Wenn Sie die Eingabetaste nicht drücken, wird die Eingabeaufforderung nicht zurückgegeben. Drücken Sie daher die Eingabetaste
[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; //→ Wird nach 30 Sekunden angezeigt
//→ Wenn Sie die Eingabetaste nicht drücken, wird die Eingabeaufforderung nicht zurückgegeben. Drücken Sie daher die Eingabetaste
[1]+  Done                    ./zombie /bin/echo "This is zombie"
[vagrant@vagrant-centos65 tmp]$ 

[Wie man Zombies vermeidet]

Methode ① Nach fork (), waitpid ()

Nach dem Verzweigen verwendet der übergeordnete Prozess waitpid, um die Beendigung des untergeordneten Prozesses abzufangen. Es liegt in der Verantwortung der Eltern, das Auftreten von Zombies zu verhindern.

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;

    //Argumentprüfung
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
        exit(1);
    }

    //Gabel, um einen untergeordneten Prozess zu erstellen
    //Für die Verarbeitung nach dem Verzweigen werden zwei Prozesse gleichzeitig ausgeführt, ein übergeordneter Prozess und ein untergeordneter Prozess.
    pid = fork();
    if (pid < 0) {
        fprintf(stderr, "fork(2) failed\n");
        exit(1);
    }

    //Der Rückgabewert von fork des untergeordneten Prozesses ist 0
    if (pid == 0) { /*Was der untergeordnete Prozess tut*/
        execl(argv[1], argv[1], argv[2], NULL);
        /* execl()Wird bei Erfolg nicht zurückgegeben, daher schlägt bei Rückgabe alles fehl*/
        perror(argv[1]);
        exit(99);
    }
    //Der Rückgabewert der Verzweigung des übergeordneten Prozesses ist die Prozess-ID des untergeordneten Prozesses.
    else {          /*Was der übergeordnete Prozess tut*/
        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);
    }
}
【Ausführungsergebnis】

Sie können mit dem Befehl ps bestätigen, dass der Zombie nicht existiert.

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

Methode ② Doppelgabel

Erstellen Sie einen untergeordneten Prozess aus einem übergeordneten Prozess und einen Enkelprozess aus einem untergeordneten Prozess. Durch das Beenden des untergeordneten Prozesses wird der Enkelprozess nicht zu einem Zombie, da der übergeordnete Prozess aus dem Enkelprozess nicht mehr vorhanden ist. Stellen Sie sicher, dass der Enkelprozess noch vorhanden ist, wenn der übergeordnete und der untergeordnete Prozess beendet werden.

Prozess Prozessの終了時間
Übergeordneter Prozess Beenden Sie nach 30 Sekunden
Untergeordneter Prozess Sofortiges Ende
Enkelprozess Beenden Sie nach 60 Sekunden

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;

    //Argumentprüfung
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
        exit(1);
    }

    //Gabel, um einen untergeordneten Prozess zu erstellen
    //Für die Verarbeitung nach dem Verzweigen werden zwei Prozesse gleichzeitig ausgeführt, ein übergeordneter Prozess und ein untergeordneter Prozess.
    pid = fork();
    if (pid < 0) {
        fprintf(stderr, "fork(2) failed\n");
        exit(1);
    }

    //Der Rückgabewert von fork des untergeordneten Prozesses ist 0
    if (pid == 0) { /*Was der untergeordnete Prozess tut*/
        pid_t pid_child;
        pid_child = fork();
        if (pid_child < 0) {
            fprintf(stderr, "child fork(2) failed\n");
            exit(1);
        }

        if (pid_child == 0) { /*Was der Enkelprozess macht*/
            execl(argv[1], argv[1], argv[2], NULL);
            /* execl()Wird bei Erfolg nicht zurückgegeben, daher schlägt bei Rückgabe alles fehl*/
            perror(argv[1]);
            exit(99);
        } else { /*Was der untergeordnete Prozess tut*/
            printf("grandchild (PID=%d) finished; ", pid_child);
            exit(0);
        }
    }
    //Der Rückgabewert der Verzweigung des übergeordneten Prozesses ist die Prozess-ID des untergeordneten Prozesses.
    else {          /*Was der übergeordnete Prozess tut*/
        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);
    }
}
【Ausführungsergebnis】

Dieses Mal verwende ich "Schlaf" anstelle von "Echo", um die Existenz eines Enkelprozesses zu überprüfen.

[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]$ 
//Zombies gibt es nicht
[vagrant@vagrant-centos65 tmp]$ ps aux | grep defunct | grep -v grep
//Der Enkelprozess existiert
[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]$ 
//Der Enkelprozess ist auch dann noch vorhanden, wenn der übergeordnete Prozess beendet wird
[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]$
//Der Enkelprozess endet ebenfalls nach 60 Sekunden
[vagrant@vagrant-centos65 tmp]$ ps aux | grep 25676 | grep -v grep
[vagrant@vagrant-centos65 tmp]$ 

Methode ③ Verwenden Sie 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;

    //Argumentprüfung
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <command> <arg>\n", argv[0]);
        exit(1);
    }

    detach_children();

    //Gabel, um einen untergeordneten Prozess zu erstellen
    //Für die Verarbeitung nach dem Verzweigen werden zwei Prozesse gleichzeitig ausgeführt, ein übergeordneter Prozess und ein untergeordneter Prozess.
    pid = fork();
    if (pid < 0) {
        fprintf(stderr, "fork(2) failed\n");
        exit(1);
    }

    //Der Rückgabewert von fork des untergeordneten Prozesses ist 0
    if (pid == 0) { /*Was der untergeordnete Prozess tut*/
        execl(argv[1], argv[1], argv[2], NULL);
        /* execl()Wird bei Erfolg nicht zurückgegeben, daher schlägt bei Rückgabe alles fehl*/
        perror(argv[1]);
        exit(99);
    }
    //Der Rückgabewert der Verzweigung des übergeordneten Prozesses ist die Prozess-ID des untergeordneten Prozesses.
    else {          /*Was der übergeordnete Prozess tut*/
    	printf("child (PID=%d) finished;\n", pid);
    	//Da das Signal im Schlaf gefangen ist, wird es währenddessen unendlich wiederholt
    	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)
{
    ;
}
【Ausführungsergebnis】
[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]$ 
//Zombies gibt es nicht
[vagrant@vagrant-centos65 tmp]$ ps aux | grep defunct | grep -v grep
// zombie_Vermeiden3-Prozess existiert
[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]$ 

[Wie man einen Zombie macht]

Ich werde Ihnen zeigen, wie Sie den in zombie.c erstellten Zombie-Prozess beenden können.

Zombies können nicht besiegt werden, indem die Zombies selbst angegriffen werden (untergeordnete Prozesse).

[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]$ 
//Töte Zombies
[vagrant@vagrant-centos65 tmp]$ kill 25933
//Du hast einen Zombie getötet, aber der Zombie existiert
[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]$ 

Ein Zombie kann besiegt werden, indem der Kopf des Zombies angegriffen wird (übergeordneter Prozess).

[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]$ 
//Beenden Sie den übergeordneten Prozess
[vagrant@vagrant-centos65 tmp]$ kill 25965
[vagrant@vagrant-centos65 tmp]$ 
[1]+  Terminated              ./zombie /bin/echo "This is zombie"
[vagrant@vagrant-centos65 tmp]$
//Es gibt keine übergeordneten Prozesse oder Zombies
[vagrant@vagrant-centos65 tmp]$ ps aux | grep -e zombie -e defunct | grep -v grep
[vagrant@vagrant-centos65 tmp]$ 

【Nachschlagewerk】

[Normale Linux-Programmierung 2. Ausgabe: Der königliche Weg der gcc-Programmierung, der aus dem Mechanismus von Linux gelernt werden kann](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)

[Referenzseite]

So erstellen Sie einen Zombie-Prozess double fork to avoid zombie process

Recommended Posts

[C-Sprache] So erstellen, vermeiden und erstellen Sie einen Zombie-Prozess
Versuchen Sie, ein Python-Modul in C-Sprache zu erstellen
Erstellen und Verwenden von statischen / dynamischen Bibliotheken in C-Sprache
Wie erstelle ich eine japanisch-englische Übersetzung?
Wie man einen lockeren Bot macht
So erstellen Sie ein Conda-Paket
Wie erstelle ich einen Crawler?
So erstellen Sie eine rekursive Funktion
So erstellen Sie eine virtuelle Brücke
Wie erstelle ich eine Docker-Datei?
[Blender] So erstellen Sie ein Blender-Plug-In
Wie erstelle ich einen Crawler?
So erstellen Sie eine Konfigurationsdatei
[C-Sprache] [Linux] Versuchen Sie, einen einfachen Linux-Befehl zu erstellen. * Fügen Sie einfach hinzu! !!
Übersicht über das Erstellen eines Server-Sockets und das Einrichten eines Client-Sockets
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
So erstellen Sie einen Klon aus Github
So teilen und speichern Sie einen DataFrame
So erstellen Sie einen Git-Klonordner
[Python] Wie man eine Klasse iterierbar macht
So erstellen Sie ein Repository aus Medien
So erstellen Sie einen benutzerdefinierten Backtrader-Indikator
Wie erstelle ich eine Pelican Site Map?
Teilen und Verarbeiten eines Datenrahmens mithilfe der Groupby-Funktion
So führen Sie einen Prozessthread nur auf einem bestimmten CPU-Kern aus
So machen Sie den Containernamen in Docker als Subdomain zugänglich
3. Verarbeitung natürlicher Sprache mit Python 1-2. So erstellen Sie einen Korpus: Aozora Bunko
Wie man ein Dialogsystem für Anfänger erstellt
So erstellen Sie erklärende Variablen und Zielfunktionen
So erstellen Sie eine JSON-Datei in Python
So erstellen Sie ein Wörterbuch mit einer hierarchischen Struktur.
So steuern Sie Multiprozesse ausschließlich in C-Sprache
Machen Sie einen Chat-Bot und üben Sie, beliebt zu sein.
So erstellen Sie ein QGIS-Plug-In (Paketerzeugung)
Ich las "Wie man ein Hacking Lab macht"
[Hinweis] So erstellen Sie eine Ruby-Entwicklungsumgebung
So erstellen Sie ein 1-zeiliges Kivy-Eingabefeld
Verfahren zur Erstellung plattformübergreifender Apps mit kivy
So erstellen Sie eine Rest-API in Django
[Hinweis] So erstellen Sie eine Mac-Entwicklungsumgebung
Ich habe versucht, einen periodischen Prozess mit CentOS7, Selenium, Python und Chrome durchzuführen
So lesen Sie Seriennummerndateien in einer Schleife, verarbeiten sie und zeichnen sie grafisch auf
C-Sprache zum Sehen und Erinnern Teil 3 Rufen Sie die C-Sprache aus Python auf (Argument) c = a + b
[Python] So erstellen Sie eine lokale Webserverumgebung mit SimpleHTTPServer und CGIHTTPServer
Lesen Sie die Python-Markdown-Quelle: So erstellen Sie einen Parser
So zeigen Sie das Änderungsdatum einer Datei in C-Sprache bis zu Nanosekunden an
So erstellen Sie ein Untermenü mit dem Plug-In [Blender]
[GCF + Python] So laden Sie Excel in GCS hoch und erstellen eine neue Tabelle in BigQuery
Wie man ein Schießspiel mit toio macht (Teil 1)
[Go] So erstellen Sie einen benutzerdefinierten Fehler für Sentry
So erstellen Sie einen USB-Stick, mit dem Linux- und Win10-Installer und Winpe UEFI starten können
So stellen Sie pyenv unter Amazon Linux und Ubuntu ein, um eine Python 3.6.0-Umgebung zu erstellen
So erstellen Sie ein Python-Paket mit VS Code
So erstellen Sie ein lokales Repository für Linux
[Python] So erstellen Sie eine Korrelationsmatrix und eine Heatmap
Grundlagen von PyTorch (2) - Wie erstelle ich ein neuronales Netzwerk?
So erstellen Sie ein einfaches TCP-Server / Client-Skript