Prozesse unter UNIX
Definition Was ist ein Prozess? Zeitliche Abfolge von Aktionen Ein Programm, das ausgeführt wird Prozesshierachie Baumstruktur INIT-Prozess ist die Wurzel (pid=1) und wird beim Booten erzeugt. Alle anderen Prozesse sind Nachfolger von INIT
Prozesshierachie init + acpid cron dhclient3 events/0 events/1 firefox bin + 6*[evince {evince}] java_vm 12*[{java_vm}] 10*[{firefox bin}] gdm gdm + Xorg x session manag ssh agent 4*[getty] gnome terminal + 9*[bash] 5*[bash ssh] bash pstree login bash vim login bash
Prozesshierachie fork Kernprozess (Prozess 0) /etc/init (Prozess 1) /etc/getty (Prozess i) /bin/login (Prozess i) Bash (Prozess i) erzeugt von Kernel fork /etc/getty (Prozess j) /bin/login (Prozess j) Bash (Prozess j) fork /etc/getty (Prozess k) /bin/login (Prozess k) Bash (Prozess k)...
Systemaufruf fork() Erzeugt einen neuen Prozess Nach Aufruf von fork() existieren 2 identische Prozesse, welche aber unabhängig voneinander ablaufen! Syntax: pid_t fork(); Rückgabewerte Beim Vaterprozess: Die PID des Kindprozesses Beim Kindprozess: 0 Fehler: -1
Systemaufruf wait() Wird im Vaterprozess benutzt Wartet auf das Beenden des Kindprozesses Syntax: pid_t wait(int *status); Rückgabewerte Die PID des Kindprozesses, der beendet wurde Fehler: -1
Systemaufruf wait() Der Exit-Status kann des Kindprozesses kann durch Makros ermittelt werden Makro WIFEXITED(status) WIFSGNALED(status) Bedeutung Ist TRUE, wenn sich ein Kindprozess beendet hat. Will man den genauen EXIT- Wert, so kann man ihn mit dem Makro WEXITSTATUS(status) erfragen Ist TRUE, wenn der Kindprozess durch ein Signal terminiert wurde, das dieser nicht abgefragt hat. Das genaue Signal kann durch das Makro WTERMSIG(status) abgefragt werden. Makros in <sys/wait.h>
Systemaufruf waitpid() Mit wait() kann allerdings nur auf die Beendigung des nächsten Prozesses gewartet werden. Mit waitpid() kann hingegen auf die Beendigung eines bestimmten Prozesses gewartet werden. Syntax: pid_t waitpid(pid_t pid, int *status, int optionen); Über das 3. Argument, optionen, kann das Verhalten von waitpid() beeinflusst werden. Folgende Möglichkeiten: WNOHANG Der Aufrufende Prozess wird nicht blockiert, wenn der Prozess >>PID<< noch nicht beendet bzw. noch nicht im Zombie-Status ist. waitpid() liefert in diesem Fall 0 zurück WUNTRACED Status des angehaltenen Kindprozesses
Systemaufruf () Überladen des aktuellen Prozesses mit neuem Code Mehrere Varianten von () l, lp, le, v und vp Die einzelnen Funktionen unterscheiden sich anhand der Endungen, wobei jeder Buchstabe folgende Bedeutung hat: Buchstabe Bedeutung e l v p Es wird eine Environmentliste (Umgebungsvariablen) als Vektor erwartet. Es werden Kommandozeilenargumente in Form einer Liste erwartet Es werden die Kommandozeilenargumente in Form eines Vektors erwartet Es wird ein Dateiname und nicht ein Pfadname als Argument zum Aufruf des Programms erwartet
() Das zweite Argument wird in der Prozesstabelle als Prozessname ausgegeben. Würde man z.b. folgendes schreiben: l( /bin/ls, wer_bin_ich, l, wd, NULL); wird trotzdem das Arbeitsverzeichnis aufgelistet. Als Prozessname, mit ps -f, würde allerdings der Name wer_bin_ich aufgelistet werden.
() Beispiele I ve. Das Beispiel ruft printenv auf und verändert die Umgebungsvariablen von diesem Prozess #include <stdio.h> #include <unistd.h> int main (void) { char *args[] = {"printenv", NULL}; char *env[] = { "SHELL=/bin/bash", "LOGNAME=a_username", "OSTYPE=L1NuX", NULL } }; return ve("/usr/bin/printenv", args, env);
() Beispiele II l Es werden Kommandozeilenargumente in Form einer Liste erwartet. Es werden keine Environmentvariablen übergeben. Stattdessen wird das aktuelle Environment benutzt. Beispiel: #include <stdio.h> #include <unistd.h> int main (void) { char *argumente[4] = { "ls", " l", "/usr/bin", NULL }; return v ("/bin/ls", argumente); }
() Beispiele III le ähnlich zu ve() - Alle Argumente werden in Listenform mit NULL gefolgt von den Umgebungsvariablen in Vektorform übergeben Beispiel: #include <stdio.h> #include <unistd.h> int main (void) { char *environment[4]; environment[0] = "SHELL=/bin/csh"; environment[1] = "LOGNAME=Wolfi"; environment[2] = "OSTYPE=LiNuX"; environment[3] = NULL; } return le("/usr/bin/ls", "ls", " d", "/tmp", "/", NULL, environment);
() Beispiele IV lp ähnlich zu ve() - Erstes Argument muss nicht, wie bei le, ein absoluter Dateiname sein Beispiel: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main (void) { return lp ("/bin/ls", "ls", " l", getenv("home"), NULL); }
() Beispiele V vp ähnlich zu lp() nur werden die Argumente als Vektor übergeben Beispiel: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main (void) { char *argumente[4]; argumente[0] = "ls"; argumente[1] = " l"; argumente[2] = getenv("home"); argumente[3] = NULL; } return vp ("/bin/ls", argumente);
() Beispiele V vp ähnlich zu lp() nur werden die Argumente als Vektor übergeben Beispiel: #include <stdio.h> #include <stdlib.h> #include <unistd.h> int main (void) { char *argumente[4]; argumente[0] = "ls"; argumente[1] = " l"; argumente[2] = getenv("home"); argumente[3] = NULL; } return vp ("/bin/ls", argumente);
Und alles gemeinsam... init fork() () Anwendung exit() wait()