Damit all diese Speisephilosophen nicht verhungern.
Kenj0418
Antworten:
105
fork()So erstellen Sie neue Prozesse in Unix. Wenn Sie anrufen fork, erstellen Sie eine Kopie Ihres eigenen Prozesses mit einem eigenen Adressraum . Auf diese Weise können mehrere Aufgaben unabhängig voneinander ausgeführt werden, als hätten sie jeweils den vollen Speicher der Maschine für sich.
Hier sind einige Verwendungsbeispiele für fork:
Ihre Shell verwendet forkdie Programme, die Sie über die Befehlszeile aufrufen.
Webserver wie Apache werden verwendet fork, um mehrere Serverprozesse zu erstellen, von denen jeder Anforderungen in seinem eigenen Adressraum verarbeitet. Wenn einer stirbt oder Speicher verliert, sind andere davon nicht betroffen, sodass er als Mechanismus für die Fehlertoleranz fungiert.
Google Chrome verwendet fork, um jede Seite in einem separaten Prozess zu behandeln. Dadurch wird verhindert, dass clientseitiger Code auf einer Seite Ihren gesamten Browser herunterfährt.
forkwird verwendet, um Prozesse in einigen parallelen Programmen (wie denen, die mit MPI geschrieben wurden) zu erzeugen . Beachten Sie, dass sich dies von der Verwendung von Threads unterscheidet , die keinen eigenen Adressraum haben und in einem Prozess vorhanden sind.
Skriptsprachen werden forkindirekt verwendet, um untergeordnete Prozesse zu starten. Beispielsweise verarbeiten Sie jedes Mal, wenn Sie einen Befehl wie subprocess.Popenin Python verwenden, forkein untergeordnetes Element und lesen dessen Ausgabe. Dadurch können Programme zusammenarbeiten.
Die typische Verwendung forkin einer Shell sieht ungefähr so aus:
int child_process_id = fork();if(child_process_id){// Fork returns a valid pid in the parent process. Parent executes this.// wait for the child process to complete
waitpid(child_process_id,...);// omitted extra args for brevity// child process finished!}else{// Fork returns 0 in the child process. Child executes this.// new argv array for the child processconstchar*argv[]={"arg1","arg2","arg3", NULL};// now start executing some other program
exec("/path/to/a/program", argv);}
Die Shell erzeugt einen untergeordneten Prozess mit execund wartet auf dessen Abschluss. Anschließend wird die eigene Ausführung fortgesetzt. Beachten Sie, dass Sie die Gabel nicht auf diese Weise verwenden müssen. Sie können immer viele untergeordnete Prozesse erzeugen, wie dies bei einem parallelen Programm der Fall ist, und jeder kann gleichzeitig ein Programm ausführen. Grundsätzlich verwenden Sie jedes Mal, wenn Sie neue Prozesse in einem Unix-System erstellen fork(). Schauen Sie sich das Windows-Äquivalent an CreateProcess.
Wenn Sie mehr Beispiele und eine längere Erklärung wünschen, hat Wikipedia eine anständige Zusammenfassung. Im Folgenden finden Sie einige Folien zur Funktionsweise von Prozessen, Threads und Parallelität in modernen Betriebssystemen.
Aufzählungszeichen 5: "oft"? Nur "oft"? Welche verwenden es nicht oder unter welchen Umständen wird fork () nicht verwendet - also auf Systemen, die fork () unterstützen.
Jonathan Leffler
19
Seltsamerweise heißt es CreateProcess () - diese verrückten Windows-Typen :-)
paxdiablo
2
Bisher noch nie realisiert, dass "Shell Fork verwendet, um die von Ihnen über die Befehlszeile aufgerufenen Programme auszuführen"!
Lazer
1
Slides Link ist gebrochen
piertoni
1
Alle Antworten besagen, dass dies fork()der Weg ist, um einen neuen Prozess unter UNIX zu erstellen, aber um pedantisch zu sein, gibt es mindestens einen anderen : posix_spawn().
Davislor
15
Mit fork () erstellt Unix neue Prozesse. An dem Punkt, an dem Sie fork () aufgerufen haben, wird Ihr Prozess geklont, und zwei verschiedene Prozesse setzen die Ausführung von dort aus fort. Bei einem von ihnen, dem Kind, gibt fork () 0 zurück. Bei dem anderen, dem Elternteil, gibt fork () die PID (Prozess-ID) des Kindes zurück.
Wenn Sie beispielsweise Folgendes in eine Shell eingeben, ruft das Shell-Programm fork () auf und führt dann den Befehl aus, den Sie (in diesem Fall telnetd) im untergeordneten Element übergeben haben, während das übergeordnete Element die Eingabeaufforderung ebenfalls erneut anzeigt als Nachricht, die die PID des Hintergrundprozesses angibt.
$ telnetd &
Aus dem Grund, warum Sie neue Prozesse erstellen, kann Ihr Betriebssystem viele Dinge gleichzeitig erledigen. Aus diesem Grund können Sie ein Programm ausführen und während der Ausführung zu einem anderen Fenster wechseln und etwas anderes tun.
fork () wird verwendet, um einen untergeordneten Prozess zu erstellen. Wenn eine fork () - Funktion aufgerufen wird, wird ein neuer Prozess erzeugt und der fork () - Funktionsaufruf gibt einen anderen Wert für das Kind und das Elternteil zurück.
Wenn der Rückgabewert 0 ist, wissen Sie, dass Sie der untergeordnete Prozess sind, und wenn der Rückgabewert eine Zahl ist (die zufällig die untergeordnete Prozess-ID ist), wissen Sie, dass Sie der übergeordnete Prozess sind. (und wenn es sich um eine negative Zahl handelt, ist die Verzweigung fehlgeschlagen und es wurde kein untergeordneter Prozess erstellt.)
Es sei denn, der Rückgabewert ist -1. In diesem Fall ist fork () fehlgeschlagen.
Jonathan Leffler
8
Mit fork () wird grundsätzlich ein untergeordneter Prozess für den Prozess erstellt, in dem Sie diese Funktion aufrufen. Immer wenn Sie ein fork () aufrufen, wird eine Null für die untergeordnete ID zurückgegeben.
pid=fork()if pid==0//this is the child processelseif pid!=0//this is the parent process
Auf diese Weise können Sie verschiedene Aktionen für Eltern und Kind bereitstellen und die Multithreading-Funktion verwenden.
fork () erstellt einen neuen untergeordneten Prozess, der mit dem übergeordneten identisch ist. Alles, was Sie danach im Code ausführen, wird von beiden Prozessen ausgeführt - sehr nützlich, wenn Sie beispielsweise einen Server haben und mehrere Anforderungen bearbeiten möchten.
Warum erstellst du ein Kind, das mit dem Elternteil identisch ist? Was nützt es?
1
Es ist wie beim Aufbau einer Armee gegen einen einzelnen Soldaten. Sie geben an, dass Ihr Programm mehr Anforderungen gleichzeitig verarbeiten kann, anstatt nacheinander.
Cloudhead
fork () gibt 0 für das Kind und die PID des Kindes für das Elternteil zurück. Das Kind kann dann einen Aufruf wie exec () verwenden, um seinen Status durch ein neues Programm zu ersetzen. So werden Programme gestartet.
Todd Gamblin
Die Prozesse sind nahezu identisch, es gibt jedoch viele subtile Unterschiede. Die offensichtlichen Unterschiede sind die aktuelle PID und die übergeordnete PID. Es gibt Probleme im Zusammenhang mit gehaltenen Sperren und gehaltenen Semaphoren. Die fork () - Handbuchseite für POSIX listet 25 Unterschiede zwischen dem Elternteil und dem Kind auf.
Jonathan Leffler
2
@kar: Sobald Sie zwei Prozesse haben, können diese getrennt von dort fortgesetzt werden und einer von ihnen könnte sich selbst (exex ()) durch ein anderes Programm vollständig ersetzen.
Vatine
4
Sie müssen Fork wahrscheinlich nicht für die tägliche Programmierung verwenden, wenn Sie Anwendungen schreiben.
Selbst wenn Sie möchten, dass Ihr Programm ein anderes Programm startet, um eine Aufgabe zu erledigen, gibt es andere einfachere Schnittstellen, die Gabel hinter den Kulissen verwenden, wie "System" in C und Perl.
Wenn Sie beispielsweise möchten, dass Ihre Anwendung ein anderes Programm wie bc startet, um eine Berechnung für Sie durchzuführen, können Sie es mit 'system' ausführen. Das System führt einen 'Fork' aus, um einen neuen Prozess zu erstellen, und einen 'Exec', um diesen Prozess in bc umzuwandeln. Sobald bc abgeschlossen ist, gibt das System die Kontrolle an Ihr Programm zurück.
Sie können auch andere Programme asynchron ausführen, aber ich kann mich nicht erinnern, wie.
Wenn Sie Server, Shells, Viren oder Betriebssysteme schreiben, möchten Sie mit größerer Wahrscheinlichkeit Fork verwenden.
Der Systemaufruf fork () wird zum Erstellen von Prozessen verwendet. Es akzeptiert keine Argumente und gibt eine Prozess-ID zurück. Der Zweck von fork () besteht darin, einen neuen Prozess zu erstellen, der zum untergeordneten Prozess des Aufrufers wird. Nachdem ein neuer untergeordneter Prozess erstellt wurde, führen beide Prozesse die nächste Anweisung nach dem Systemaufruf fork () aus. Deshalb müssen wir den Elternteil vom Kind unterscheiden. Dies kann durch Testen des zurückgegebenen Werts von fork () erfolgen:
Wenn fork () einen negativen Wert zurückgibt, war die Erstellung eines untergeordneten Prozesses nicht erfolgreich. fork () gibt eine Null an den neu erstellten untergeordneten Prozess zurück. fork () gibt einen positiven Wert, die Prozess-ID des untergeordneten Prozesses, an das übergeordnete Element zurück. Die zurückgegebene Prozess-ID ist vom Typ pid_t, der in sys / types.h definiert ist. Normalerweise ist die Prozess-ID eine Ganzzahl. Darüber hinaus kann ein Prozess die Funktion getpid () verwenden, um die diesem Prozess zugewiesene Prozess-ID abzurufen. Daher kann nach dem Systemaufruf von fork () ein einfacher Test feststellen, welcher Prozess das untergeordnete Element ist. Bitte beachten Sie, dass Unix eine exakte Kopie des Adressraums der Eltern erstellt und diese dem Kind gibt. Daher haben der übergeordnete und der untergeordnete Prozess separate Adressräume.
Lassen Sie es uns anhand eines Beispiels verstehen, um die obigen Punkte klar zu machen. In diesem Beispiel werden übergeordnete und untergeordnete Prozesse nicht unterschieden.
#include<stdio.h>#include<string.h>#include<sys/types.h>#define MAX_COUNT 200#define BUF_SIZE 100void main(void){pid_t pid;int i;char buf[BUF_SIZE];
fork();
pid = getpid();for(i =1; i <= MAX_COUNT; i++){
sprintf(buf,"This line is from pid %d, value = %d\n", pid, i);
write(1, buf, strlen(buf));}}
Angenommen, das obige Programm wird bis zum Aufruf von fork () ausgeführt.
Wenn der Aufruf von fork () erfolgreich ausgeführt wird, erstellt Unix zwei identische Kopien von Adressräumen, eine für das übergeordnete und das andere für das untergeordnete Element. Beide Prozesse beginnen ihre Ausführung bei der nächsten Anweisung nach dem Aufruf von fork (). In diesem Fall beginnen beide Prozesse ihre Ausführung bei der Zuweisung
pid =.....;
Beide Prozesse starten ihre Ausführung direkt nach dem Systemaufruf fork (). Da beide Prozesse identische, aber separate Adressräume haben, haben diese vor dem Aufruf von fork () initialisierten Variablen in beiden Adressräumen dieselben Werte. Da jeder Prozess seinen eigenen Adressraum hat, sind alle Änderungen unabhängig von den anderen. Mit anderen Worten, wenn das übergeordnete Element den Wert seiner Variablen ändert, wirkt sich die Änderung nur auf die Variable im Adressraum des übergeordneten Prozesses aus. Andere durch fork () -Aufrufe erstellte Adressräume sind nicht betroffen, obwohl sie identische Variablennamen haben.
Was ist der Grund für die Verwendung von write anstelle von printf? Dies liegt daran, dass printf () "gepuffert" ist, was bedeutet, dass printf () die Ausgabe eines Prozesses zusammenfasst. Während die Ausgabe für den übergeordneten Prozess gepuffert wird, kann das Kind auch printf verwenden, um einige Informationen auszudrucken, die ebenfalls gepuffert werden. Da die Ausgabe nicht sofort an den Bildschirm gesendet wird, erhalten Sie möglicherweise nicht die richtige Reihenfolge des erwarteten Ergebnisses. Schlimmer noch, die Ausgabe der beiden Prozesse kann auf seltsame Weise gemischt werden. Um dieses Problem zu beheben, können Sie das "ungepufferte" Schreiben verwenden.
Wenn Sie dieses Programm ausführen, wird möglicherweise Folgendes auf dem Bildschirm angezeigt:
................This line is from pid 3456, value 13This line is from pid 3456, value 14................This line is from pid 3456, value 20This line is from pid 4617, value 100This line is from pid 4617, value 101................This line is from pid 3456, value 21This line is from pid 3456, value 22................
Die Prozess-ID 3456 kann diejenige sein, die dem Elternteil oder dem Kind zugewiesen ist. Aufgrund der Tatsache, dass diese Prozesse gleichzeitig ausgeführt werden, werden ihre Ausgangsleitungen auf ziemlich unvorhersehbare Weise vermischt. Darüber hinaus wird die Reihenfolge dieser Zeilen vom CPU-Scheduler festgelegt. Wenn Sie dieses Programm erneut ausführen, erhalten Sie möglicherweise ein völlig anderes Ergebnis.
Multiprocessing ist für die Datenverarbeitung von zentraler Bedeutung. Beispielsweise kann Ihr IE oder Firefox einen Prozess zum Herunterladen einer Datei für Sie erstellen, während Sie noch im Internet surfen. Oder während Sie ein Dokument in einem Textverarbeitungsprogramm ausdrucken, können Sie immer noch verschiedene Seiten betrachten und damit noch etwas bearbeiten.
Fork () wird verwendet, um neue Prozesse zu erstellen, wie jeder Körper geschrieben hat.
Hier ist mein Code, der Prozesse in Form eines Binärbaums erstellt. Er fordert Sie auf, die Anzahl der Ebenen zu scannen, bis zu denen Sie Prozesse im Binärbaum erstellen möchten
#include<unistd.h>#include<fcntl.h>#include<stdlib.h>int main(){int t1,t2,p,i,n,ab;
p=getpid();
printf("enter the number of levels\n");fflush(stdout);
scanf("%d",&n);
printf("root %d\n",p);fflush(stdout);for(i=1;i<n;i++){
t1=fork();if(t1!=0)
t2=fork();if(t1!=0&& t2!=0)break;
printf("child pid %d parent pid %d\n",getpid(),getppid());fflush(stdout);}
waitpid(t1,&ab,0);
waitpid(t2,&ab,0);return0;}
Zuerst muss man verstehen, was ein Systemaufruf von fork () ist. Lassen Sie mich erklären
Der Systemaufruf fork () erstellt das genaue Duplikat des übergeordneten Prozesses. Er erstellt das Duplikat des übergeordneten Stapels, des Heaps, der initialisierten Daten und der nicht initialisierten Daten und teilt den Code im schreibgeschützten Modus mit dem übergeordneten Prozess.
Der Fork-Systemaufruf kopiert den Speicher auf der Basis von Copy-on-Write. Dies bedeutet, dass das Kind eine virtuelle Speicherseite erstellt, wenn ein Kopieren erforderlich ist.
Jetzt Zweck der Gabel ():
Fork () kann an dem Ort verwendet werden, an dem es eine Arbeitsteilung gibt, wie ein Server mehrere Clients verarbeiten muss. Daher muss der Elternteil die Verbindung regelmäßig akzeptieren. Der Server gibt also einen Fork für jeden Client aus, um Lese- und Schreibvorgänge auszuführen.
fork()wird verwendet, um einen untergeordneten Prozess zu erzeugen. Normalerweise wird es in ähnlichen Situationen wie beim Threading verwendet, es gibt jedoch Unterschiede. Im Gegensatz zu Threads fork()werden ganze separate Prozesse erstellt. Dies bedeutet, dass das Kind und das Elternteil, während sie an dem fork()aufgerufenen Punkt direkte Kopien voneinander sind, vollständig getrennt sind und weder auf den Speicherplatz des anderen zugreifen können (ohne zu den normalen Problemen zu wechseln) Sie gehen, um auf den Speicher eines anderen Programms zuzugreifen.
fork()wird immer noch von einigen Serveranwendungen verwendet, hauptsächlich von solchen, die als Root auf einem * NIX-Computer ausgeführt werden und Berechtigungen löschen, bevor Benutzeranforderungen verarbeitet werden. Es gibt noch einige andere Anwendungsfälle, aber die meisten Menschen sind jetzt zum Multithreading übergegangen.
Ich verstehe die Wahrnehmung nicht, dass "die meisten Menschen" zum Multithreading übergegangen sind. Prozesse sind hier, um zu bleiben, ebenso wie Threads. Niemand ist von beiden "weitergezogen". Bei der parallelen Programmierung sind die größten und gleichzeitigsten Codes Mehrprozessprogramme mit verteiltem Speicher (z. B. MapReduce und MPI). Dennoch würden sich die meisten Menschen für OpenMP oder ein Shared-Memory-Paradigma für einen Multicore-Computer entscheiden, und GPUs verwenden heutzutage Threads, aber darüber hinaus gibt es noch viel mehr. Ich wette jedoch, dass mehr Codierer auf dieser Site auf der Server-Seite auf Prozessparallelität stoßen als auf Multithreading.
Da Fork den aktuellen Prozess kopiert, sind im Wesentlichen alle verschiedenen möglichen Optionen für einen Prozess standardmäßig festgelegt, sodass der Programmierer sie nicht bereitstellt.
Im Windows-Betriebssystem hingegen müssen Programmierer die Funktion CreateProcess verwenden, die VIEL komplizierter ist und das Auffüllen einer vielfältigen Struktur zum Definieren der Parameter des neuen Prozesses erfordert.
Zusammenfassend lässt sich sagen, dass der Grund für das Gabeln (im Vergleich zum Ausführen) die Einfachheit bei der Erstellung neuer Prozesse ist.
Fork () -Systemaufruf zum Erstellen eines untergeordneten Prozesses. Es ist ein genaues Duplikat des übergeordneten Prozesses. Fork kopiert Stapelabschnitte, Heapabschnitte, Datenabschnitte, Umgebungsvariablen und Befehlszeilenargumente vom übergeordneten Element.
Mit der Funktion fork () wird ein neuer Prozess erstellt, indem der vorhandene Prozess dupliziert wird, von dem aus er aufgerufen wird. Der vorhandene Prozess, von dem aus diese Funktion aufgerufen wird, wird zum übergeordneten Prozess und der neu erstellte Prozess zum untergeordneten Prozess. Wie bereits erwähnt, handelt es sich bei dem Kind um eine Kopie des Elternteils, es gibt jedoch einige Ausnahmen.
Das Kind hat eine eindeutige PID wie jeder andere Prozess, der im Betriebssystem ausgeführt wird.
Das Kind hat eine übergeordnete Prozess-ID, die mit der PID des
Prozesses übereinstimmt , der es erstellt hat.
Ressourcenauslastung und CPU-Zeitzähler werden im untergeordneten Prozess auf Null zurückgesetzt.
Antworten:
fork()
So erstellen Sie neue Prozesse in Unix. Wenn Sie anrufenfork
, erstellen Sie eine Kopie Ihres eigenen Prozesses mit einem eigenen Adressraum . Auf diese Weise können mehrere Aufgaben unabhängig voneinander ausgeführt werden, als hätten sie jeweils den vollen Speicher der Maschine für sich.Hier sind einige Verwendungsbeispiele für
fork
:fork
die Programme, die Sie über die Befehlszeile aufrufen.fork
, um mehrere Serverprozesse zu erstellen, von denen jeder Anforderungen in seinem eigenen Adressraum verarbeitet. Wenn einer stirbt oder Speicher verliert, sind andere davon nicht betroffen, sodass er als Mechanismus für die Fehlertoleranz fungiert.fork
, um jede Seite in einem separaten Prozess zu behandeln. Dadurch wird verhindert, dass clientseitiger Code auf einer Seite Ihren gesamten Browser herunterfährt.fork
wird verwendet, um Prozesse in einigen parallelen Programmen (wie denen, die mit MPI geschrieben wurden) zu erzeugen . Beachten Sie, dass sich dies von der Verwendung von Threads unterscheidet , die keinen eigenen Adressraum haben und in einem Prozess vorhanden sind.fork
indirekt verwendet, um untergeordnete Prozesse zu starten. Beispielsweise verarbeiten Sie jedes Mal, wenn Sie einen Befehl wiesubprocess.Popen
in Python verwenden,fork
ein untergeordnetes Element und lesen dessen Ausgabe. Dadurch können Programme zusammenarbeiten.Die typische Verwendung
fork
in einer Shell sieht ungefähr so aus:Die Shell erzeugt einen untergeordneten Prozess mit
exec
und wartet auf dessen Abschluss. Anschließend wird die eigene Ausführung fortgesetzt. Beachten Sie, dass Sie die Gabel nicht auf diese Weise verwenden müssen. Sie können immer viele untergeordnete Prozesse erzeugen, wie dies bei einem parallelen Programm der Fall ist, und jeder kann gleichzeitig ein Programm ausführen. Grundsätzlich verwenden Sie jedes Mal, wenn Sie neue Prozesse in einem Unix-System erstellenfork()
. Schauen Sie sich das Windows-Äquivalent anCreateProcess
.Wenn Sie mehr Beispiele und eine längere Erklärung wünschen, hat Wikipedia eine anständige Zusammenfassung. Im Folgenden finden Sie einige Folien zur Funktionsweise von Prozessen, Threads und Parallelität in modernen Betriebssystemen.
quelle
fork()
der Weg ist, um einen neuen Prozess unter UNIX zu erstellen, aber um pedantisch zu sein, gibt es mindestens einen anderen :posix_spawn()
.Mit fork () erstellt Unix neue Prozesse. An dem Punkt, an dem Sie fork () aufgerufen haben, wird Ihr Prozess geklont, und zwei verschiedene Prozesse setzen die Ausführung von dort aus fort. Bei einem von ihnen, dem Kind, gibt fork () 0 zurück. Bei dem anderen, dem Elternteil, gibt fork () die PID (Prozess-ID) des Kindes zurück.
Wenn Sie beispielsweise Folgendes in eine Shell eingeben, ruft das Shell-Programm fork () auf und führt dann den Befehl aus, den Sie (in diesem Fall telnetd) im untergeordneten Element übergeben haben, während das übergeordnete Element die Eingabeaufforderung ebenfalls erneut anzeigt als Nachricht, die die PID des Hintergrundprozesses angibt.
Aus dem Grund, warum Sie neue Prozesse erstellen, kann Ihr Betriebssystem viele Dinge gleichzeitig erledigen. Aus diesem Grund können Sie ein Programm ausführen und während der Ausführung zu einem anderen Fenster wechseln und etwas anderes tun.
quelle
fork () wird verwendet, um einen untergeordneten Prozess zu erstellen. Wenn eine fork () - Funktion aufgerufen wird, wird ein neuer Prozess erzeugt und der fork () - Funktionsaufruf gibt einen anderen Wert für das Kind und das Elternteil zurück.
Wenn der Rückgabewert 0 ist, wissen Sie, dass Sie der untergeordnete Prozess sind, und wenn der Rückgabewert eine Zahl ist (die zufällig die untergeordnete Prozess-ID ist), wissen Sie, dass Sie der übergeordnete Prozess sind. (und wenn es sich um eine negative Zahl handelt, ist die Verzweigung fehlgeschlagen und es wurde kein untergeordneter Prozess erstellt.)
http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html
quelle
Mit fork () wird grundsätzlich ein untergeordneter Prozess für den Prozess erstellt, in dem Sie diese Funktion aufrufen. Immer wenn Sie ein fork () aufrufen, wird eine Null für die untergeordnete ID zurückgegeben.
Auf diese Weise können Sie verschiedene Aktionen für Eltern und Kind bereitstellen und die Multithreading-Funktion verwenden.
quelle
fork () erstellt einen neuen untergeordneten Prozess, der mit dem übergeordneten identisch ist. Alles, was Sie danach im Code ausführen, wird von beiden Prozessen ausgeführt - sehr nützlich, wenn Sie beispielsweise einen Server haben und mehrere Anforderungen bearbeiten möchten.
quelle
Sie müssen Fork wahrscheinlich nicht für die tägliche Programmierung verwenden, wenn Sie Anwendungen schreiben.
Selbst wenn Sie möchten, dass Ihr Programm ein anderes Programm startet, um eine Aufgabe zu erledigen, gibt es andere einfachere Schnittstellen, die Gabel hinter den Kulissen verwenden, wie "System" in C und Perl.
Wenn Sie beispielsweise möchten, dass Ihre Anwendung ein anderes Programm wie bc startet, um eine Berechnung für Sie durchzuführen, können Sie es mit 'system' ausführen. Das System führt einen 'Fork' aus, um einen neuen Prozess zu erstellen, und einen 'Exec', um diesen Prozess in bc umzuwandeln. Sobald bc abgeschlossen ist, gibt das System die Kontrolle an Ihr Programm zurück.
Sie können auch andere Programme asynchron ausführen, aber ich kann mich nicht erinnern, wie.
Wenn Sie Server, Shells, Viren oder Betriebssysteme schreiben, möchten Sie mit größerer Wahrscheinlichkeit Fork verwenden.
quelle
system()
. Ich habe darüber gelesen,fork()
weil ich möchte, dass mein C-Code ein Python-Skript ausführt.Gabel schafft neue Prozesse. Ohne Fork hätten Sie ein Unix-System, das nur init ausführen könnte.
quelle
Der Systemaufruf fork () wird zum Erstellen von Prozessen verwendet. Es akzeptiert keine Argumente und gibt eine Prozess-ID zurück. Der Zweck von fork () besteht darin, einen neuen Prozess zu erstellen, der zum untergeordneten Prozess des Aufrufers wird. Nachdem ein neuer untergeordneter Prozess erstellt wurde, führen beide Prozesse die nächste Anweisung nach dem Systemaufruf fork () aus. Deshalb müssen wir den Elternteil vom Kind unterscheiden. Dies kann durch Testen des zurückgegebenen Werts von fork () erfolgen:
Wenn fork () einen negativen Wert zurückgibt, war die Erstellung eines untergeordneten Prozesses nicht erfolgreich. fork () gibt eine Null an den neu erstellten untergeordneten Prozess zurück. fork () gibt einen positiven Wert, die Prozess-ID des untergeordneten Prozesses, an das übergeordnete Element zurück. Die zurückgegebene Prozess-ID ist vom Typ pid_t, der in sys / types.h definiert ist. Normalerweise ist die Prozess-ID eine Ganzzahl. Darüber hinaus kann ein Prozess die Funktion getpid () verwenden, um die diesem Prozess zugewiesene Prozess-ID abzurufen. Daher kann nach dem Systemaufruf von fork () ein einfacher Test feststellen, welcher Prozess das untergeordnete Element ist. Bitte beachten Sie, dass Unix eine exakte Kopie des Adressraums der Eltern erstellt und diese dem Kind gibt. Daher haben der übergeordnete und der untergeordnete Prozess separate Adressräume.
Lassen Sie es uns anhand eines Beispiels verstehen, um die obigen Punkte klar zu machen. In diesem Beispiel werden übergeordnete und untergeordnete Prozesse nicht unterschieden.
Angenommen, das obige Programm wird bis zum Aufruf von fork () ausgeführt.
Wenn der Aufruf von fork () erfolgreich ausgeführt wird, erstellt Unix zwei identische Kopien von Adressräumen, eine für das übergeordnete und das andere für das untergeordnete Element. Beide Prozesse beginnen ihre Ausführung bei der nächsten Anweisung nach dem Aufruf von fork (). In diesem Fall beginnen beide Prozesse ihre Ausführung bei der Zuweisung
Beide Prozesse starten ihre Ausführung direkt nach dem Systemaufruf fork (). Da beide Prozesse identische, aber separate Adressräume haben, haben diese vor dem Aufruf von fork () initialisierten Variablen in beiden Adressräumen dieselben Werte. Da jeder Prozess seinen eigenen Adressraum hat, sind alle Änderungen unabhängig von den anderen. Mit anderen Worten, wenn das übergeordnete Element den Wert seiner Variablen ändert, wirkt sich die Änderung nur auf die Variable im Adressraum des übergeordneten Prozesses aus. Andere durch fork () -Aufrufe erstellte Adressräume sind nicht betroffen, obwohl sie identische Variablennamen haben.
Was ist der Grund für die Verwendung von write anstelle von printf? Dies liegt daran, dass printf () "gepuffert" ist, was bedeutet, dass printf () die Ausgabe eines Prozesses zusammenfasst. Während die Ausgabe für den übergeordneten Prozess gepuffert wird, kann das Kind auch printf verwenden, um einige Informationen auszudrucken, die ebenfalls gepuffert werden. Da die Ausgabe nicht sofort an den Bildschirm gesendet wird, erhalten Sie möglicherweise nicht die richtige Reihenfolge des erwarteten Ergebnisses. Schlimmer noch, die Ausgabe der beiden Prozesse kann auf seltsame Weise gemischt werden. Um dieses Problem zu beheben, können Sie das "ungepufferte" Schreiben verwenden.
Wenn Sie dieses Programm ausführen, wird möglicherweise Folgendes auf dem Bildschirm angezeigt:
Die Prozess-ID 3456 kann diejenige sein, die dem Elternteil oder dem Kind zugewiesen ist. Aufgrund der Tatsache, dass diese Prozesse gleichzeitig ausgeführt werden, werden ihre Ausgangsleitungen auf ziemlich unvorhersehbare Weise vermischt. Darüber hinaus wird die Reihenfolge dieser Zeilen vom CPU-Scheduler festgelegt. Wenn Sie dieses Programm erneut ausführen, erhalten Sie möglicherweise ein völlig anderes Ergebnis.
quelle
Multiprocessing ist für die Datenverarbeitung von zentraler Bedeutung. Beispielsweise kann Ihr IE oder Firefox einen Prozess zum Herunterladen einer Datei für Sie erstellen, während Sie noch im Internet surfen. Oder während Sie ein Dokument in einem Textverarbeitungsprogramm ausdrucken, können Sie immer noch verschiedene Seiten betrachten und damit noch etwas bearbeiten.
quelle
Fork () wird verwendet, um neue Prozesse zu erstellen, wie jeder Körper geschrieben hat.
Hier ist mein Code, der Prozesse in Form eines Binärbaums erstellt. Er fordert Sie auf, die Anzahl der Ebenen zu scannen, bis zu denen Sie Prozesse im Binärbaum erstellen möchten
AUSGABE
quelle
Zuerst muss man verstehen, was ein Systemaufruf von fork () ist. Lassen Sie mich erklären
Der Systemaufruf fork () erstellt das genaue Duplikat des übergeordneten Prozesses. Er erstellt das Duplikat des übergeordneten Stapels, des Heaps, der initialisierten Daten und der nicht initialisierten Daten und teilt den Code im schreibgeschützten Modus mit dem übergeordneten Prozess.
Der Fork-Systemaufruf kopiert den Speicher auf der Basis von Copy-on-Write. Dies bedeutet, dass das Kind eine virtuelle Speicherseite erstellt, wenn ein Kopieren erforderlich ist.
Jetzt Zweck der Gabel ():
quelle
fork()
wird verwendet, um einen untergeordneten Prozess zu erzeugen. Normalerweise wird es in ähnlichen Situationen wie beim Threading verwendet, es gibt jedoch Unterschiede. Im Gegensatz zu Threadsfork()
werden ganze separate Prozesse erstellt. Dies bedeutet, dass das Kind und das Elternteil, während sie an demfork()
aufgerufenen Punkt direkte Kopien voneinander sind, vollständig getrennt sind und weder auf den Speicherplatz des anderen zugreifen können (ohne zu den normalen Problemen zu wechseln) Sie gehen, um auf den Speicher eines anderen Programms zuzugreifen.fork()
wird immer noch von einigen Serveranwendungen verwendet, hauptsächlich von solchen, die als Root auf einem * NIX-Computer ausgeführt werden und Berechtigungen löschen, bevor Benutzeranforderungen verarbeitet werden. Es gibt noch einige andere Anwendungsfälle, aber die meisten Menschen sind jetzt zum Multithreading übergegangen.quelle
Die Gründe für fork () im Vergleich zu einer exec () - Funktion zum Initiieren eines neuen Prozesses werden in einer Antwort auf eine ähnliche Frage zum Unix-Stack-Austausch erläutert .
Da Fork den aktuellen Prozess kopiert, sind im Wesentlichen alle verschiedenen möglichen Optionen für einen Prozess standardmäßig festgelegt, sodass der Programmierer sie nicht bereitstellt.
Im Windows-Betriebssystem hingegen müssen Programmierer die Funktion CreateProcess verwenden, die VIEL komplizierter ist und das Auffüllen einer vielfältigen Struktur zum Definieren der Parameter des neuen Prozesses erfordert.
Zusammenfassend lässt sich sagen, dass der Grund für das Gabeln (im Vergleich zum Ausführen) die Einfachheit bei der Erstellung neuer Prozesse ist.
quelle
Fork () -Systemaufruf zum Erstellen eines untergeordneten Prozesses. Es ist ein genaues Duplikat des übergeordneten Prozesses. Fork kopiert Stapelabschnitte, Heapabschnitte, Datenabschnitte, Umgebungsvariablen und Befehlszeilenargumente vom übergeordneten Element.
Siehe: http://man7.org/linux/man-pages/man2/fork.2.html
quelle
Mit der Funktion fork () wird ein neuer Prozess erstellt, indem der vorhandene Prozess dupliziert wird, von dem aus er aufgerufen wird. Der vorhandene Prozess, von dem aus diese Funktion aufgerufen wird, wird zum übergeordneten Prozess und der neu erstellte Prozess zum untergeordneten Prozess. Wie bereits erwähnt, handelt es sich bei dem Kind um eine Kopie des Elternteils, es gibt jedoch einige Ausnahmen.
Das Kind hat eine eindeutige PID wie jeder andere Prozess, der im Betriebssystem ausgeführt wird.
Das Kind hat eine übergeordnete Prozess-ID, die mit der PID des
Prozesses übereinstimmt , der es erstellt hat.
Ressourcenauslastung und CPU-Zeitzähler werden im untergeordneten Prozess auf Null zurückgesetzt.
Der Satz anstehender Signale im Kind ist leer.
Das Kind erbt keine Timer von seinem Elternteil
Beispiel:
Wenn nun der obige Code kompiliert und ausgeführt wird:
quelle