Threads und fork() in C
Cruz
- programmiertechnik
Hallo,
ich bin dabei eine Applikation zu planen, die ich dann in C schreiben möchte. Es wird ein kurzes aber knackiges Programm, das viel Speicher und CPU Zeit benötigt. Das Programm soll neben einer aufwendigen mathematischen Berechnung in einem regelmäßigen Takt von 10 Millisekunden ein UDP Paket an einen Server schicken. Es wäre am besten, wenn der Versand der UDP Pakete als ein gesonderter Thread abläuft, damit die Taktung nicht von der Rechengeschwindigkeit des Hauptprozesses abhängt. Mein Plan ist es ein Kindprozess per fork() zu erzeigen und per IPC (shared memory block) die Daten vom Hauptprozess bereit stellen zu lassen.
Grundsätzlich erstmal, ist dieser Plan soweit in Ordnung, oder rollen schon einige Fussnägel hoch?
Nun habe ich ja gelesen, dass fork() den ganzen Adressraum des parents kopiert. Das ist gar nicht gut. Der kleine Thread braucht eigentlich nur zwei drei interne Variablen und Zugriff auf den shared memory block. Der Elternprozess hingegen soll Megabyteweise Daten im Speicher halten. Die werden dann alle kopiert wenn ich fork() aufrufe und blockieren dann nutzlos meinen halben Speicher? Oder kann ich was dagegen tun?
Vielen Dank
Cruz
Moin!
ich bin dabei eine Applikation zu planen, die ich dann in C schreiben möchte. Es wird ein kurzes aber knackiges Programm, das viel Speicher und CPU Zeit benötigt.
Ein _kurzes_ Programm? Was hast du vor ;-)
Es wäre am besten, wenn der Versand der UDP Pakete als ein gesonderter Thread abläuft […]. Mein Plan ist es ein Kindprozess per fork() zu erzeigen und per IPC (shared memory block) die Daten vom Hauptprozess bereit stellen zu lassen.
fork() erzeugt einen neuen Prozess, ein Thread ist etwas Anderes. Aber du möchtest vielleicht wirklich lieber „nur“ einen Thread erzeugen, damit das nicht passieren kann, wenn fork() tatsächlich so funktioniert:
Nun habe ich ja gelesen, dass fork() den ganzen Adressraum des parents kopiert.
Außerdem brauchst du dann keine IPC und Shared Memory, weil der Thread auf deine globalen Variablen zugreifen kann. Dazu solltest du dich aber außerdem mit Monitoren bzw. Semaphoren beschäftigen.
Schönen Montagabend,
Robert
Hallo Cruz,
Mein Plan ist es ein Kindprozess per fork() zu erzeigen und per IPC (shared memory block) die Daten vom Hauptprozess bereit stellen zu lassen.
Das wäre eine Möglichkeit.
Nun habe ich ja gelesen, dass fork() den ganzen Adressraum des parents kopiert.
Ja und nein. In der Regel wird heutzutage eine Art "Copy on Write" verwendet, d.h. es wird erst kopiert, sobald was geändert wird, d.h. wenn Du direkt nach fork() ein execve() o.ä. machst, dann wird idR. aber nichts kopiert. Das ist aber für Dich nicht wirklich interessant, da Du ja im Prozess selbst bleiben willst, was dann irgendwann unausweichlich zum Kopieren führt.
Das ist gar nicht gut. Der kleine Thread braucht eigentlich nur zwei drei interne Variablen und Zugriff auf den shared memory block. Der Elternprozess hingegen soll Megabyteweise Daten im Speicher halten. Die werden dann alle kopiert wenn ich fork() aufrufe und blockieren dann nutzlos meinen halben Speicher?
Ja. Bzw. sobald Du fork() aufrufst und mehr als bloß trivialen Code verwendet hast. Du hast 3 Optionen:
* Du nutzt richtiges fork(). Dann brauchst Du allerdings zusätzlich Shared
Memory als IPC-Mechansimus, d.h. schau Dir mal die shm*-Funktionen an.
Damit Dein Speicher nicht zu voll wird, kannst Du im Kindprozess erstmal
alles unnötige wieder loswerden (das betrifft den Elternprozess nicht),
per free() oder so. Dann gibt's nur kurzfristig einen Speicherpeak. Oder
Du startest den Kindprozess von Anfang an und signalisierst ihm über IPC-
Mechanismen erst an einer bestimmten Stelle aus dem Elternprozess, dass
er jetzt anfangen soll.
* Du nutzt clone(). Damit kannst Du erreichen, dass sich Kind- und Eltern-
prozess einen gemeinsamen Speicherbereich teilen (ohne "normales" Shared
Memory, wenn auch der Mechansimus evtl. ähnlich implementiert ist) und
Dein Speicherverbrauch reduziert sich. Hier musst Du allerdings höllisch
aufpassen, denn wenn der Speicherbereich der gleiche ist, können sich
Eltern- und Kindprozess gegenseitig etwas kaputt machen.
* Du nutzt gleich richtige Threads (unter UNIX pthreads). Die haben gegen-
über clone() den Vorteil, dass die Locking-Mechanismen (Mutexes, etc.)
in Threads bereits sauber implementiert sind und Du Dir deswegen keine
Gedanken darüber machen müsstest.
Mein Favorit wäre die Thread-Variante, die auch Robert vorgeschlagen hat.
Viele Grüße,
Christian
Hi!
Danke (auch an Robert) für die Hinweise. Ich habe mir angeschaut wie man mit pthreads programmiert und ja, das ist genau das was ich gesucht habe. Ich habe auch schon ein Skelettprogramm implementiert und es funktioniert traumhaft.
Viele Grüße,
Cruz