Fork-Systemaufruf in C

Fork System Call C



Der Systemaufruf fork() wird verwendet, um Kindprozesse in einem C-Programm zu erstellen. fork() wird verwendet, wenn eine parallele Verarbeitung in Ihrer Anwendung erforderlich ist. Die Systemfunktion fork() ist in den Headern definiert sys/types.h und unistd.h . In einem Programm, in dem Sie fork verwenden, müssen Sie auch den Systemaufruf wait() verwenden. Der Systemaufruf wait() wird verwendet, um im übergeordneten Prozess auf die Beendigung des untergeordneten Prozesses zu warten. Um einen Kindprozess zu beenden, wird der Systemaufruf exit() im Kindprozess verwendet. Die Funktion wait() ist im Header definiert sys/wait.h und die Funktion exit() ist im Header definiert stdlib.h .

Abb. 1: Grundlegender fork()-Workflow

Abb. 1: Grundlegender fork()-Workflow







In diesem Artikel zeige ich Ihnen, wie Sie den Systemaufruf fork() verwenden, um untergeordnete Prozesse in C zu erstellen. Beginnen wir also.



fork() Syntax und Rückgabewert:

Die Syntax der Systemfunktion fork() lautet wie folgt:



pid_t Gabel(Leere);

Die Systemfunktion fork() akzeptiert keine Argumente. Es gibt eine ganze Zahl vom Typ . zurück pid_t .





Bei Erfolg gibt fork() die PID des Kindprozesses zurück, die größer als 0 ist. Innerhalb des Kindprozesses ist der Rückgabewert 0. Wenn fork() fehlschlägt, wird -1 zurückgegeben.

Einfache Gabel() Beispiel:

Ein einfaches fork()-Beispiel ist unten angegeben:



#enthalten
#enthalten
#enthalten
#enthalten
#enthalten

inthauptsächlich(Leere) {
pid_t pid=Gabel();

wenn(pid== 0) {
druckenf ('Kind => PPID: %d PID: %d ',getppid(),getpid());
Ausfahrt (EXIT_SUCCESS);
}
anders wenn(pid> 0) {
druckenf ('Elternteil => PID: %d ',getpid());
druckenf ('Warten, bis der untergeordnete Prozess abgeschlossen ist. ');
Warten(NULL);
druckenf ('Kinderprozess beendet. ');
}
anders {
druckenf ('Kind-Prozess kann nicht erstellt werden. ');
}

RückkehrEXIT_SUCCESS;
}

Hier habe ich fork() verwendet, um einen untergeordneten Prozess aus dem Haupt- / Elternprozess zu erstellen. Dann habe ich die PID (Prozess-ID) und PPID (Parent-Prozess-ID) von Kind- und Elternprozess gedruckt. Auf dem übergeordneten Prozess wird wait(NULL) verwendet, um zu warten, bis der untergeordnete Prozess beendet ist. Beim Kindprozess wird exit() verwendet, um den Kindprozess zu beenden. Wie Sie sehen, ist die PID des übergeordneten Prozesses die PPID des untergeordneten Prozesses. Also, der Kindprozess 24738 gehört zum übergeordneten Prozess 24731 .

Sie können auch Funktionen verwenden, um Ihr Programm modularer zu gestalten. Hier habe ich verwendet processTask() und parentTask() Funktionen für die untergeordneten und übergeordneten Prozesse. So wird fork() tatsächlich verwendet.

#enthalten
#enthalten
#enthalten
#enthalten
#enthalten

LeereKindAufgabe() {
druckenf ('Hallo Welt ');
}

LeereparentTask() {
druckenf ('Hauptaufgabe. ');
}

inthauptsächlich(Leere) {
pid_t pid=Gabel();

wenn(pid== 0) {
KindAufgabe();
Ausfahrt (EXIT_SUCCESS);
}
anders wenn(pid> 0) {
Warten(NULL);
parentTask();
}
anders {
druckenf ('Kind-Prozess kann nicht erstellt werden.');
}

RückkehrEXIT_SUCCESS;
}

Die Ausgabe des obigen Programms:

Ausführen mehrerer untergeordneter Prozesse mit fork() und Loop:

Sie können auch Schleife verwenden, um so viele untergeordnete Prozesse zu erstellen, wie Sie benötigen. Im folgenden Beispiel habe ich 5 untergeordnete Prozesse mit der for-Schleife erstellt. Ich habe auch die PID und PPID aus den untergeordneten Prozessen gedruckt.

#enthalten
#enthalten
#enthalten
#enthalten
#enthalten

inthauptsächlich(Leere) {
zum(intich= 1;ich<= 5;ich++) {
pid_t pid=Gabel();

wenn(pid== 0) {
druckenf ('Untergeordneter Prozess => PPID=%d, PID=%d ',getppid(),getpid());
Ausfahrt (0);
}
anders {
druckenf ('Elternprozess => PID=%d ',getpid());
druckenf ('Warten, bis untergeordnete Prozesse abgeschlossen sind... ');
Warten(NULL);
druckenf ('Kind-Prozess beendet. ');
}
}

RückkehrEXIT_SUCCESS;
}

Wie Sie sehen, ist die ID des übergeordneten Prozesses in allen untergeordneten Prozessen gleich. Sie gehören also alle demselben Elternteil an. Sie werden auch linear ausgeführt. Einer nach dem anderen. Die Steuerung von Kindprozessen ist eine anspruchsvolle Aufgabe. Wenn Sie mehr über die Linux-Systemprogrammierung und ihre Funktionsweise erfahren, können Sie den Ablauf dieser Prozesse nach Belieben steuern.

Beispiel aus dem echten Leben:

Verschiedene komplexe mathematische Berechnungen wie md5, sha256 usw. Hash-Generierung erfordern viel Rechenleistung. Anstatt solche Dinge im selben Prozess wie das Hauptprogramm zu berechnen, können Sie einfach den Hash eines Kindprozesses berechnen und den Hash an den Hauptprozess zurückgeben.

Im folgenden Beispiel habe ich in einem Kindprozess einen 4-stelligen PIN-Code generiert und an den Elternprozess, das Hauptprogramm, gesendet. Von dort habe ich dann den PIN-Code ausgedruckt.

#enthalten
#enthalten
#enthalten
#enthalten
#enthalten

intgetPIN() {
// PPID und PID als Seed verwenden
srand (getpid() +getppid());
intGeheimnis= 1000 + Reihe () % 9000;
RückkehrGeheimnis;
}

inthauptsächlich(Leere) {
intfd[2];
Rohr(fd);
pid_t pid=Gabel();

wenn(pid> 0) {
nah dran(0);
nah dran(fd[1]);
nach(fd[0]);

intgeheime Nummer;
Größe_treadBytes=lesen(fd[0], &geheime Nummer, Größe von(geheime Nummer));

druckenf ('Warten auf PIN... ');
Warten(NULL);
druckenf ('Gelesene Bytes: %ld ',readBytes);
druckenf ('PIN: %d ',geheime Nummer);
}
anders wenn(pid== 0) {
nah dran(1);
nah dran(fd[0]);
nach(fd[1]);

intGeheimnis=getPIN();
schreiben(fd[1], &Geheimnis, Größe von(Geheimnis));
Ausfahrt (EXIT_SUCCESS);
}

RückkehrEXIT_SUCCESS;
}

Wie Sie sehen, erhalte ich jedes Mal, wenn ich das Programm ausführe, einen anderen 4-stelligen PIN-Code.

So verwenden Sie im Wesentlichen den Systemaufruf fork() in Linux. Danke, dass Sie diesen Artikel gelesen haben.