Projekt1: Prozesse unter Unix Teil II Prozesse / Systemaufrufe Fehlerbehandlung Übung Betriebssysteme, Uni Innsbruck 1 2.0 Prozesse / Systemaufrufe unter Unix 2.1 Was sind Prozesse ? 2.2 Was sind Systemaufrufe ? 2.3 Systemaufruf fork() 2.4 Systemaufruf wait() 2.5 Systemaufruf exec() 2.6 Systemaufruf gets() 2.7 Systemaufruf strtok() 2.8 Systemaufruf getpid() 2.9 Systemaufruf ipcrm / ipcs 2.10 Message Queues (msgget, msgsnd, msgrcv, msgctl) Übung Betriebssysteme, Uni Innsbruck 2 Übersicht Übersicht 3.0 Fehlerbehandlung 3.1 Was versteht man unter Fehlerbehandlung ? 3.2 Fehlerbehandlung mit errno.h 3.3 Fehlerbehandlung mit perror() Übung Betriebssysteme, Uni Innsbruck 3 Übersicht „Prozesse und Systemaufrufe unter Unix“ 2.1 Was sind Prozesse ? 2.2 Was sind Systemaufrufe ? 2.3 Systemaufruf fork() 2.4 Systemaufruf wait() 2.5 Systemaufruf exec() 2.6 Systemaufruf gets() 2.7 Systemaufruf strtok() 2.8 Systemaufruf getpid() 2.9 Systemaufruf ipcrm / ipcs 2.10 Message Queues (msgget, msgctl, msgsnd, msgrcv) Übung Betriebssysteme, Uni Innsbruck 4 2.1 Was sind Prozesse ? Definitionen Ein Prozess ist eine zeitliche Abfolge einer Reihe von Aktionen erzeugt durch Ausführung einer Folge von Instruktionen. Ein Prozess ist ein in Ausführung befindliches Programm. Prozesshierarchie Ähnlich dem Dateisystem sind sämtliche Prozesse in einer baumartigen Hierarchie angeordnet. Alle Prozesse sind Nachfolger des Prozesses init (pid = 1), der während des Bootens als erster gestartet wird. Durch die Kombination der Systemcalls „fork“ und „exec“ erzeugt init für jeden Terminaleingang einen Prozess getty (bzw. ttymon) der den interaktiven Zugang zum System ermöglicht. Nach erfolgreichem Login wird die Shell gestartet. Übung Betriebssysteme, Uni Innsbruck 5 Übung Betriebssysteme, Uni Innsbruck 6 2.1 Was sind Prozesse ? 2.2 Was sind Systemaufrufe ? Interface zwischen Prozess und Betriebssystem Direkter Zugriff auf Funktionalität des Kernels Unterschied zwischen Funktionsaufruf und SystemCall? Funktion als Teil des Benutzerprogrammes SystemCall exekutiert Kernel-Code SystemCall schreibt die Parameter auf bestimmte Adresse und führt dann einen TRAP. BS übernimmt dann die Kontrolle. Ein Systemaufruf erzeugt, zerstört oder benutzt verschiedene Ressourcen, die durch das Betriebssystem verwaltet werden. Beispiele für Ressourcen: Prozesse Dateien Speicher Semaphore Übung Betriebssysteme, Uni Innsbruck 7 Übung Betriebssysteme, Uni Innsbruck 8 Systemaufruf 2.3 Systemaufruf fork() fork() erzeugt einen neuen Prozess unter UNIX. Nach der Ausführung des fork()-Aufrufs existieren zwei identische Prozesse, die vollständig unabhängig voneinander ablaufen. verschiedene Prozess-IDs Rückgabewerte der Funktion fork(): im Vater: die Prozeß-ID: (PID) des Sohn-Prozesses im Sohn: der Wert 0 im Fehlerfall: der Wert -1 Übung Betriebssysteme, Uni Innsbruck 9 Syntax #include <unistd.h> int fork(); Übung Betriebssysteme, Uni Innsbruck 10 2.3 Systemaufruf fork() 2.4 Systemaufruf wait() Mittels der Funktion wait() wartet ein Vater-Prozess auf das Ende eines Sohn-Prozesses. Der Rückgabewert der Funktion ist die PID des Sohn-Prozesses, der gerade beendet wurde. Ebenso wird in den Parameter „status“ durch das Betriebssystem der Exit-Code des Sohn-Prozesses, der durch den Befehl exit() gegeben ist, eingetragen. Im Fehlerfall (wenn kein Sohn-Prozess vorhanden ist) gibt die Funktion den Rückgabewert -1 zurück und die Variable errno wird auf den entsprechenden Wert gesetzt. Syntax #include <sys/wait.h> int wait(int *status); Übung Betriebssysteme, Uni Innsbruck 11 2.5 Systemaufruf exec() Programmcode wird in den laufenden Prozess geladen. Überladen eines Prozesses mit einem neuen Code 5 verschiedene Routine mit kleinen Unterschieden: execl, execle, execv, execlp und execvp. file Pointer auf die Datei, die ausgeführt werden soll argv Die Argumente, mit denen das Programm ausgeführt werden soll Übung Betriebssysteme, Uni Innsbruck 12 Syntax int execvp( const char *file, char *const argv[]) 2.6 Systemaufruf gets() einlesen einer Character-Sequenz von stin bis „\n“ oder EOF gelesen wurde erzeugt einen String durch eliminieren von „\n“ und anhängen von „\0“ Beispiel #include<stdio.h> int main(int argc, char **argv) { char buf[255]; printf ("type something:"); if ( gets(buf) != NULL ) printf ("you typed:%s\n",buf); } Alternative: scanf Übung Betriebssysteme, Uni Innsbruck 13 Eine Zeichenkette wird anhand eines Trennzeichens in mehrere Teile (Token) zerlegt. Die zu zerlegende Zeichenkette muss nur beim ersten Aufruf angegeben werden, alle folgenden Aufrufe benötigen nur das Trennzeichen (siehe Beispiel). Retourniert wird der Teilstring bis zum nächsten Trennzeichen Syntax #include <string.h> char *strtok( char *str1, const char *delimiter ); Übung Betriebssysteme, Uni Innsbruck 14 2.7 Systemaufruf strtok() 2.7 Systemaufruf strtok() Beispiel char str[] = ”now # is the time for all # good men to come to the # aid"; char delims[] = "#"; char *result = NULL; Resultat result is "now " result is " is the time for all " result is " good men to come to the " result is " aid" Übung Betriebssysteme, Uni Innsbruck 15 result = strtok( str, delims ); while( result != NULL ) { printf( "result is \"%s\"\n", result ); result = strtok( NULL, delims ); } 2.8 Systemaufruf getpid() Liefert die eindeutige Prozess-ID (auch PID genannt) eines Prozesses. Elternprozesses: getppid() Beispiel #include<stdio.h> int main(int argc, char **argv) { char buf[255]; int pid=getpid(); printf ("my pid:%d\n",pid) } Übung Betriebssysteme, Uni Innsbruck 16 2.9 Systemaufruf ipcrm / ipcs ipcs: zeigt Interprozesskommunikationsressourcen an (ipc status) Kommando zum Auflisten der bereits vergebenen IPC-Ressourcen (Semaphoren, Message Queues und Shared Memory) Enthält neben den Schlüsseln und der ID auch den Namen des Besitzers dieser Ressource ipcrm: Ressourcen löschen (ipc remove) falls ein Prozess seine eigenen Ressourcen nicht löscht • gib die Ressourcen mit ipcrm frei Als Parameter dienen die ID der Ressource und der Typ. ipcsfree löscht alle IPC-Ressourcen eines Benutzers Pflicht: vor dem Ausloggen Übung Betriebssysteme, Uni Innsbruck 17 2.9 Systemaufruf ipcrm / ipcs T ID KEY Message Queues: q 0 0x3c340863 q 1 0x3e340863 Shared Memory: m 1300 0xd29cf630 m 1203 0x73746174 Semaphores: s 1 0x41365ad3 s 2 0x01090522 s 1769472 0x89a5cac4 ipcrm -m 1300: ipcrm -M 0xd29cf630: ipcrm -s 1769472: ipcrm -S 0x89a5cac4: ipcrm -q 0: MODE OWNER GROUP -Rrw--w--w--rw-r--r-- root root root root --rw-r------rw-rw-rw- oracle daq dba cms --ra-ra-ra--ra-r--r---ra-r----- root root oracle root root dba löscht Shared Memory mit der ID 1300 löscht Shared Memory mit dem KEY 0xd29cf630 löscht Semaphor mit der ID 1769472 löscht Semaphor mit dem KEY 0x89a5cac4 löscht Message Queue mit der ID 0 Übung Betriebssysteme, Uni Innsbruck 18 ipcs IPC status from <running system> as of Tue Feb 4 20:39:43 CET 2003 2.10 Message Queues (msgget, msgsnd, msgrcv, msgctl) Message Queues: Übertragung von Nachrichten zwischen Prozessen. Nach Einrichten einer solchen Message Queue kann ein Prozess Nachrichten an eine bestimmte (oder mehrere) Message Queues schicken bzw. zu empfangen. Übung Betriebssysteme, Uni Innsbruck 19 Übung Betriebssysteme, Uni Innsbruck 20 2.10 Message Queues 2.10 Message Queues (msgget, msgsnd, msgrcv, msgctl) Neue Message Queues anlegen bzw. auf bestehende referenzieren mittels msgget() Syntax int msgget ( key_t key, int msgflg ) msgflg IPC_CREAT : IPC_EXCL : Übung Betriebssysteme, Uni Innsbruck 21 key Eindeutiger Schlüssel der Message Queue falls noch keine Message Queue mit dem Schlüssel key existiert, wird eine neue angelegt, anderfalls auf die existierende MQ zugegriffen. nur in Verbindung mit IPC_CREAT sinnvoll. Existiert bereits eine Message Queue mit dem Schlüssel 2.10 Message Queues (msgget, msgsnd, msgrcv, msgctl) msgsnd wird benutzt, um Nachrichten an andere Prozesse zu schicken Syntax int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg ) Übung Betriebssysteme, Uni Innsbruck 22 msqid Ist die Message Queue-ID msgp Ist ein Zeiger auf den Nachrichtenpuffer msgsz Gibt die Länge der Nachricht an (ohne die Länge des Nachrichtentyps) msgflg Kann entweder 0 oder IPC_NOWAIT sein (im Fall von IPC_NOWAIT wird nicht gewartet, falls es nicht möglich sein sollte, in den Puffer des Empfängerprozesses zu schreiben) 2.10 Message Queues (msgget, msgsnd, msgrcv, msgctl) msgrcv wird benutzt, um Nachrichten von anderen Prozessen zu empfangen Syntax int msgrcv (int msqid, struct msgbuf *msgp, int msgsz, int msgtype, int msgflg ) Übung Betriebssysteme, Uni Innsbruck 23 msqid Ist die Message Queue-ID msgp Ist ein Zeiger auf den Nachrichtenpuffer msgsz Gibt die Länge der Nachricht an (ohne die Länge des Nachrichtentyps) msgtype Gibt an, welche Nachrichten gelesen werden sollen msgflg Kann entweder 0 oder IPC_NOWAIT sein (im Fall von IPC_NOWAIT wird nicht gewartet, falls sich keine Nachricht im Empfangspuffer befindet) 2.10 Message Queues (msgget, msgsnd, msgrcv, msgctl) msgctl wird benutzt, um Message Queues zu verwalten msqid Ist die Message Queue-ID cmd Gibt das Kommando an ( IPC_RMID, um die Queue zu löschen ) buf Wird als Kommando IPC_STAT angegeben (d.h. die Struktur einer Nachricht wird angefordert), wird die Struktur im Speicherbereich abgelebt, auf den buf zeigt Übung Betriebssysteme, Uni Innsbruck 24 Syntax int msgctl ( int msgqid, int cmd, struct msqid_ds *buf ) 3.1 Was versteht man unter Fehlerbehandlung ? 3.2 Fehlerbehandlung mit errno.h 3.3 Fehlerbehandlung mit perror() Übung Betriebssysteme, Uni Innsbruck 25 Übersicht „3.0 Fehlerbehandlung“ 3.1 Was ist Fehlerbehandlung ? Systemaufrufe unter Unix haben eine einheitliche Konvention zur Rückgabe von Werten: Rückgabewerte jedes Systemaufrufs sind vom Typ int Im Fehlerfall wird -1 geliefert Wird ein Systemcall nicht wie gewünscht ausgeführt, wird die externe Systemvariable errno zusätzlich gesetzt (die verschiedenen Möglichkeiten von errno können in errno.h nachgelesen werden) Die Funktion strerror wandelt den Fehlercode von errno in einen String um, der die Fehlerursache beschreibt (dieser sollte in jeder Fehlermeldung verwendet werden) Übung Betriebssysteme, Uni Innsbruck 26 Deklariert die globale Variable errno, die von verschiedenen Funktionen im Fehlerfall gesetzt wird Sowie alle Werte, die diese annehmen kann, als Konstante. Übung Betriebssysteme, Uni Innsbruck 27 3.2 Fehlerbehandlung mit errno.h 3.3 Fehlerbehandlung mit perror() perror() gibt eine Fehlermeldung auf stderror aus, die den letzten Fehler beschreibt, der von einem Systemcall oder einer LibraryRoutine erzeugt wurde. Die Fehler-Nachricht bezieht sich auf die Variable errno des Systems, die von diesen Funktionen im Fehlerfall gesetzt wird. Syntax void perror( char *s ) Wenn der Parameter s ein beliebiger String ist, wird dieser String gefolgt von einem Doppelpunkt und einem Blank und anschließend die Fehler-Nachricht ausgegeben. Ist der Parameter s gleich NULL, wird nur die Fehler-Nachricht ausgegeben. Übung Betriebssysteme, Uni Innsbruck 28