PROGRAMMIEREN MIT UNIX/LINUX-SYSTEMAUFRUFEN 2. UNIX/Linux-Prozessverwaltung und zugehörige Systemaufrufe Wintersemester 2016/17
2. Die UNIX/LINUX-Prozessverwaltung Aufgaben: 1. Erzeugen neuer Prozesse 2. Laden u. Ausführen von Prozessen 3. Selbstbeenden bzw. Abbrechen von Prozessen 4. Warten auf andere Prozesse (bzw. auf Ereignisse oder Signale) 2.1 Systemaufrufe der UNIX/LINUX-Prozessverwaltung wichtigste davon: fork( ) exec*(...) exit(...) wait(...) erzeugt neuen Prozess durch (fast vollständiges) Klonen des aufrufenden Prozesses aufrufender Prozess wechseltvon ihm ausgeführtes Programm [* Es existieren verschiedene Varianten, die durch nach exec folgende(s) Zeichen unterschieden werden.] Selbstbeendigung des aufrufenden Prozesses aufrufender Prozess wartet auf(beliebigen) Kindprozess 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... ws 2016/17 H.-A. Schindler Folie: 2-2
UNIX/LINUX-Prozessverwaltung: Prozess-Erzeugung spezielles Konzept (anders als bei anderen Betriebssystemen) jeder Prozess hat Elternprozess( parentprocess ) und ist selbst Kindprozess( child process ) (Ausnahme: Urprozess 0... ein Systemprozess) damit existieren Prozesse stets in Prozesshierarchien parent Ur- Prozess child(ren) grand-child(ren) 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / fork( ) ws 2016/17 H.-A. Schindler Folie: 2-3
UNIX/LINUX-Prozessverwaltung: Systemaufruf fork() Syntax: rw = fork( ) (parameterlos) Rückkehrwert Wirkungsweise: erzeugt neuen Prozess durch Klonen des aufrufenden Prozesses dabei alle Prozessbestandteile dupliziert!!(mit ganz wenigen aber sehr wichtigen Ausnahmen!!) Ausnahmen: Prozess-ID: Kind erhält (selbstverständlich!) eigenen Prozess-Identifikator Rückkehrwert rw des Systemaufrufs rw = fork( ) : rw = 0... Kindprozess rw = <pid des Kindes>... Elternprozess rw = -1 parent child fork... Fehler, Systemaufruf konnte nicht ausgeführt werden 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / fork( ) ws 2016/17 H.-A. Schindler Folie: 2-4
UNIX/LINUX-Prozessverwaltung: Systemaufruf fork() Verwendung im Programm (Prinzip): #include <unistd.h> int <rw_fork>; 7 <rw_fork> = fork(); (ohne Parameter) Konkretes Beispiel: #include <unistd.h> int ab; 7 ab = fork(); Variable Symbol Typ Bedeutung Wert <rw_fork> int Rückkehrwert Interpretation 0 O.K. nur als Wert der Variablen rw_forkbei Childprozessmöglich (hieran erkennt Childprozess sich sebst) >0 O.K. Variablenwert bei Parentprozess (Wert ist Prozess-ID des gerade erzeugten Childprozesses) -1 Feh- (nur bei Parentprozess möglich); ler fork() wurde nicht ausgeführt 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / fork( ) ws 2016/17 H.-A. Schindler Folie: 2-5
Beispielprogramm 3.c #include <unistd.h> #include <stdio.h> main() { if(fork() == 0) { // Kind-Prozess printf("ich bin der Kind-Prozess. - Ich heisse: %d\n",getpid()); printf("mein Vater (oder meine Mutter?) heisst: %d\n\n",getppid()); M: gotom; } else { // Eltern-Prozess printf("\nich bin der Eltern-Prozess. - \ Meine Identifikationsnummer ist: %d\n\n", getpid()); } wait(); printf("hier ist wieder der Eltern-Prozess.\ \nendlich brauche ich nicht mehr auf mein Kind zu warten!\n\n"); } 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / fork( ) ws 2016/17 H.-A. Schindler Folie: 2-6
UNIX/LINUX-Prozessverwaltung: Systemaufruf exec*(..) soll ein Prozess ein anderes Programm ausführen, ist nach fork() noch der exec*( )-Systemaufruf anzuwenden (von to execute... ausführen) exec*( ) überschreibt Daten-u. Textbereich mit den entsprechenden Teilen des spezifizierten (ausführbaren) Programms Nach der (erfolgreichen!) Ausführung von exec*() führt ein Prozess ein anderes Programm aus!! Prozess-Attribute Stack (Kern-Modus) Programmcode initialisierte Daten nicht initialis. Daten Stack (Nutzermodus) Prozessliste BS-Bereich Prozess- Bereich Text- Daten- Prozessdeskriptor (Prozesskontrollblock) exec*( neues Programm ) aus neuem Programm Programmcode initialisierte Daten nicht initialis. Daten Prozessattribute Stack (Kern-Modus) Programmcode initialisierte Daten nicht initialis. Daten Stack (Nutzermodus) Prozessliste BS-Bereich Prozess- Bereich Text- Daten- 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / exec*( ) ws 2016/17 H.-A. Schindler Folie: 2-7
UNIX/LINUX-Prozessverwaltung: Systemaufruf exec*(..) Prozessdeskriptor (Prozesskontrollblock) PCB Prozess-Attribute Prozessliste Prozessattribute Prozessliste Stack (Kern-Modus) Programmcode initialisierte Daten nicht initialis. Daten Stack (Nutzermodus) BS-Bereich Prozess- Bereich Text- Daten- exec*( neues Programm ) aus neuem Programm: Programmcode initialisierte Daten nicht initialis. Daten Stack (Kern-Modus) Programmcode initialisierte Daten nicht initialis. Daten Stack Ausführbares (Nutzermodus) Programm: heute im ELF-Format (siehe gleichfalls 2. Übung) BS-Bereich Text- Daten- 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / exec*( ) ws 2016/17 H.-A. Schindler Folie: 2-8
UNIX/LINUX-Prozessverwaltung: Systemaufruf exec*(..) Verwendung im Programm (Prinzip): int <rw_exec>; 7 <rw_exec> = execl( <pfad>/<program>, <program>, 0); Konkretes Beispiel: int c; 7 c = execl( d1/p1, p1, 0); Variable Symbol Typ Bedeutung Wert <rw_exec> int <pfad> <program> Rückkehrwert absoluter oder relativer Pfadname Programmname (letzte Komponente im Pfad) 0 Stringabschluss Interpretation -1 Feh- exec*(7) nicht ausgeführt; bei erfolgler reicher Ausführung rw_exec nicht mehr zugänglich 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / exec*( ) ws 2016/17 H.-A. Schindler Folie: 2-9
UNIX/LINUX-Prozessverwaltung: Systemaufruf wait(..) Verwendung im Programm (Prinzip): int <rw_wait>, <status>; 7 <rw_wait> = wait(&<status>); Konkretes Beispiel: int x, z; 7 x = wait(&z); Variable Symbol Typ Bedeutung Wert <rw_wait> int Rückkehrwert Interpretation >0 O.K. Prozess-ID des Childprozesses, der beendet wurde -1 Feh- es existierte kein Childprozess ler <status> Status des Childprozesses & Adress-Symbol 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / wait( ) ws 2016/17 H.-A. Schindler Folie: 2-10
Beispielprogramm 5.c #include <unistd.h> #include <stdio.h> main() { if (fork() == 0) { // child proc printf("kindprozess\n\n"); execl("/usr/bin/test","test", NULL); printf("systemaufruf execl(): fehlgeschlagen\n\n"); } else { // parent proc printf("\nelternprozess\n\n"); } wait(); } 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / wait( ) ws 2016/17 H.-A. Schindler Folie: 2-11
Aufgabenstellung: 1. Studieren Sie das einfache C-Programm 1.c. Übersetzen Sie dieses mit dem C-Compiler und führen Sie anschließend das übersetzte Programm aus. Wie sind die dabei erfolgten Ausgaben, insbesondere deren Anzahl zu erklären? 2. Falls Sie keine befriedigende Erklärung finden, verwenden Sie in gleicher Weise das Programm 2.c. Der parameterlose Systemaufruf getpid() liefert die Prozess-Nr. (= Prozess-Identifikator pid) des aufrufenden Prozesses. 3. Verfahren Sie mit Programm 3.c analog zu 1.c bzw. 2.c. Untersuchen Sie dann die durch das UNIX-Kommando ps (z.b. in der Form ps al ) aufgelisteten Prozesse mit ihren Parametern und interpretieren Sie die erfolgten Ausgaben! Brechen Sie dann mit dem UNIX-Kommando kill -9 <Prozess-Nummer> den Kindprozess ab. Interpretieren Sie die dadurch erfolgte Ausgabe und überprüfen Sie nochmals mit ps die noch existierenden Prozesse. 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / Aufgabenstellung ws 2016/17 H.-A. Schindler Folie: 2-12
Aufgabenstellung: 4. Übersetzen Sie jetzt das Programm 5.c und führen Sie es aus! Warum funktioniert der execl()-systemaufruf nicht? 5. Erzeugen Sie jetzt in bekannter Weise aus dem C-Programm 4.c ein ausführbares Programm, welches (z.b.) TEST heißen soll. Korrigieren Sie dann in 5.c den im Systemaufruf execl(..) enthaltenen Pfadnamen unter dem das ausführbare Programm TEST zu erreichen ist. Nach der Korrektur erzeugen Sie aus 5.c wieder ein ausführbares Programm und starten dieses. Interpretieren Sie die erfolgten Ausgaben! 6. Studieren Sie noch Programm 6.c und experimentieren Sie! 7. Sie können sich zur vorliegenden Thematik weitere Experimente ausdenken und durchführen. 2. UNIX/Linux-Prozessverwaltung / 2.1 Systemaufrufe... / Aufgabenstellung ENDE 2 ws 2016/17 H.-A. Schindler Folie: 2-13