Beendigung von Prozessen Normale Beendigung –durch Ende von main –durch Aufruf von exit() Anormale Beendigung –Aufruf von abort() –interne oder externe.

Slides:



Advertisements
Ähnliche Präsentationen
Be.as WEB Technologie
Advertisements

Präsentation PS: Klasse File von Janko Lange, Thomas Lung, Dennis Förster, Martin Hiller, Björn Schöbel.
10.2 Wechselseitiger Ausschluss in Hardware
Wiederholung Betriebssystem bietet eine Abstraktion der Hardware an:
Funktionen.
Beim Start eines Prozesses in Windows NT, 2000 wird a der Programmtext aus der exe-Datei ab der dort angegebenen Adresse gespeichert.
C Tutorium – Fehlerbehandlung – Knut Stolze. 2 Grundsatz Also ist auch nach jedem Funktionsaufruf auf Fehler zu prüfen!! Jeder(!) Funktionsaufruf kann.
C Tutorium – Semaphoren –
2 Systemdienste Wiederholungsempfehlung: Rechnerorganisation Beachte: Systemaufrufe sind sprachunabhängig. Ihre Beschreibung bezieht sich daher auf das.
Kapitel 6.1 Nebenläufigkeit und wechselseitiger Ausschluss
10 Streams JavaHS Merseburg WS 05/06 E/A - Ströme (Streams) in Java.
Java: Objektorientierte Programmierung
Java: Dynamische Datentypen
Strukturen. In einer Struktur kann eine beliebige Anzahl von Komponenten (Daten) mit unterschiedlichen Datentypen (im Gegensatz zu Feldern) zusammengefaßt.
Ein Beispiel in Java.
Klassenvariable. Da man für jede Kuh bzw. jede Henne auf dem Markt den gleichen Preis für ein Liter Milch, bzw. den gleichen Preis für ein Ei bekommt,
Polymorphie (Vielgestaltigkeit)
Polymorphie (Vielgestaltigkeit)
Objekte und Arbeitsspeicher
Dynamischer Speicher. In einer Funktion wird z.B. mit der Deklaration int i; Speicher auf dem sogenannten Stack reserviert. Wenn die Funktion verlassen.
1 Named Pipes alias FIFO Haben einen Eintrag im Dateisystem und sind somit durch Zugriffsrechte identifizierbar Ermöglichen die Kommunikation zwischen.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 7 Claudio Moraga, Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Kapitel 10 Claudio Moraga; Gisbert Dittrich FBI Unido
PKJ 2005/1 Stefan Dissmann Methoden (Motivation) Idee: Identische Programmabschnitte zusammenfassen und mit einem Namen versehen Vorteile: Übersichtlichkeit.
PKJ 2005/1 Stefan Dissmann Ausblick Es fehlen noch: Möglichkeiten zum Strukturieren größerer Programme Umgang mit variabler Zahl von Elementen Umgang mit.
Zusammenfassung Vorwoche
PKJ 2005/1 Stefan Dissmann Zusammenfassung Vorwoche Methoden sind mit einem Namen versehene Programmabschnitte besitzen Rückgabetyp, Namen, Parameterliste.
Die Skriptsprache Perl (5) Wolfgang Friebel DESY Zeuthen.
DVG Methoden 1 Methoden. 2 int dezi = Integer.parseInt(args[0]); boolean vz = (dezi>=0); dezi = Math.abs(dezi); String Bin = ""; do { } while.
DVG Klassen und Objekte
EDV Parallelprogrammierung1 Parallelprogrammierung mit JAVA.
Weiteres Programm Studium des Breitendurchlaufs Hierzu
Wir müssen also überlegen: Implementierung der Knoten, Implementierung der Kanten, daraus: Implementierung des Graphen insgesamt. Annahme: die Knoteninhalte.
Einführung MySQL mit PHP
Error Handling unter Visual FoxPro. © 1999 TMN-Systemberatung GmbH ON ERROR n ON ERROR DO ERRHAND WITH error(), sys(16), message(), lineno(1) – Globales.
Einfach verkettete Listen (OOP)
Steuerung externer Komponenten über ein USB-Interface.
PSI - Überblick und Szenarien
Einführung in die Programmiersprache C 3.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig.
Javakurs FSS 2012 Lehrstuhl Stuckenschmidt
Präsentation C Tutorium von Daniel J. Nowak Folie 1 C Tutorium.
Einführung in die Programmierung
Einführung in die Programmiersprache C 4
Dynamische Datentypen
Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Algorithmen und Datenstrukturen Übungsmodul 5 Dr. W. Narzt u. Dr. A. Stritzinger.
Betriebssysteme Übung Tutorium „System Calls & Multipgrogramming“
Betriebssysteme Übung 2. Tutorium. Task 1 – Locks (1) Wozu Locks? Dienen dazu, exklusiven Zugriff auf eine Ressource sicherzustellen Lock = binäre Semaphore.
Objectives Verstehen was unterDelegate verstanden wird
Informatik II Grundlagen der Programmierung Programmieren in C Benutzerinteraktion / Ein- und Ausgabe Hochschule Fulda – FB ET Sommersemester
Informatik Grundlagen, WS04, Seminar 7
Alois Schütte Advanced System Programming 2 Interprozeßkommunikation  2.1 JVM Ablaufumgebung  2.2 Java Native Interface (JNI)  Verwendung von.
C Tutorium – Shared Memory – Knut Stolze. 2 Shared Memory Ein Speicherbereich, auf den mehrere Prozesse Zugriff haben – Also kein privater Speicher –
Übung Betriebssysteme, Uni Innsbruck 1 Projekt1: Prozesse unter Unix Teil II Prozesse / Systemaufrufe Fehlerbehandlung.
Funktionen. Aufgabe : Eingabe zweier Zahlen ---> Minimum bestimmen Dann nochmals Eingabe zweier Zahlen ---> Minimum bestimmen.
Funktionen, Felder und Parameter- übergabe. Funktionsaufruf mit Feld als Parameter: Parameter = Name des Feldes.
Java Programme nur ein bisschen objektorientiert.
Funktionen (Zweck und Eigenschaften) Funktionen sind Unterprogramme, die einen bestimmten Zweck erfüllen Sie zerlegen Probleme in kleine, abgeschlossene.
Strukturen (Eigenschaften) Strukturen dienen zur Zusammenfassung mehrerer Komponenten verschiedener Typen zu einer Einheit, die dann mit gemeinsamen Namen.
Center for Biotechnology Bielefeld Bioinformatics Service Netzwerk - Programmierung Kommunikation von Prozessen Signale und Pipes Alexander Sczyrba
Center for Biotechnology Bielefeld Bioinformatics Service Netzwerk - Programmierung Prozesse Alexander Sczyrba Jan Krüger.
Netzwerke - Protokolle
1.Event Queue.
Netzwerk - Programmierung
Netzwerk - Programmierung
Einführung in die Programmierung
Implementieren von Klassen
 Präsentation transkript:

Beendigung von Prozessen Normale Beendigung –durch Ende von main –durch Aufruf von exit() Anormale Beendigung –Aufruf von abort() –interne oder externe Signale

Exit Status Jeder Prozess hat Exit Status, der an aufrufenden Prozess (meist shell) zurückgegeben wird. Exit Status undefiniert wenn: –automatische Rückkehr durch Ende von main() –Aufruf von return in main // ohne Angabe von Rückgabewert –Aufruf von exit; // ohne RetWert $? gibt exit status des letzten von shell gestarteten Kommandos zurück: echo $? Programmierer sollte immer Exit Status definieren: exit(0); return(0)

Verwaiste Kindprozesse Elternprozess wird beendet, bevor alle Kindprozesse beendet sind. init Prozess wird neuer Elternprozess.

Zombie-Prozesse Elternprozess kann mit wait bzw waitpid Beendigungsstatus (~exit status) von Kindprozess erfragen (und auf Kind warten wenn Kind läuft). Wenn Elternprozess nicht auf Beendigung von Kind wartet (mit wait), wie kann er (später) Beendigungsstatus von Kind erfahren? Lösung: zombie-Prozess: System speichert bei Beendigung von Prozess, auf den nicht gewartet wird, Informationen (u.a. exit stat, PID, CPU-Zeit)

Verhindern von Zombies Einbauen von Signalhandler der SIGCHLD abfängt und gleich wait() aufruft. Siehe Später! fork zweimal aufrufen: Programm kreirt Kindprozess der wiederum Kind kreirt bevor er sich beendet. Enkelprozess ist nun verwaist und bekommt init als Vater. init ruft bei Ende von Kind immer wait auf!

Warten auf Beendigung #includes: sys/types.h und sys/wait.h pid_t wait(int *status); pid_t waitpid(pid_t pid, int *status,int options) Verhalten der Funktionen: –Wenn ein Kind bereits früher beendet, kehrt wait(pid) sofort zurück; Rückgabewert: PID des beendeten Kinds –Rückkehr mit Fehler wenn keine Kinder existieren –Blockierung, wenn alle Kinder noch aktiv

Unterschiede wait/ waitpid wait wartet nur auf nächste Beendigung von beliebigem Kind kann aufrufenden Prozess blockieren waitpid wartet auf Beendigung von bestimmtem Kind mit Option kann Blockierung unterbunden werden

Beendigungsstatus int *status: call by reference Beendigungsstatus ist binärcodiert in Makros definiert, mit denen man Code interpretierten kann: WIFEXITED(status): liefert TRUE, wenn Kind sich normal beendet hat. WIFEXITSTATUS liefert Exit- Status. WIFSIGNALED TRUE, wenn Kind durch Signal (anormal) beendet. Mit WTERMSIG kann Signalnummer erfragt werden. WIFSTOPPED: Kind wurde angehalten. WSTOPSIG(status) liefert Nummer des Signals, das Prozess angehalten hat. (z.B ctrl-Z)

waitpid mit waitpid() kann auf bestimmten Prozess gewartet werden: pid_t waitpid(pid_t pid, int *status,int options) pid == -1: identisch zu wait=warten auf beliebigen Prozess pid > 0 auf Kind mit pid warten. ( pid < -1 Auf Kind warten, dessen ProzessgruppenID gleich |pid| ist ) options: Konstanten mit OR | verknüpfen: WNOHANG: Wenn Kind mit pid nicht verfügbar blockiert Prozess nicht sondern leifert 0 als Returnwert.

IPC Mechanismen in Linux Signale message queues shared memory semaphore pipes

Signale Interrupts die von HW oder SW erzeugt werden, wenn bei Programmausführung Ausnahmesituationen auftreten: – z.b. Division durch 0 (SIGFPE) –Drücken von Strg-C –Zugriff auf unerlaubte Speicheradr. (segment violation: SIGSEGV) –Signale von der Funktion kill ( -TERM -KILL –9) –SW-Signale (z.b. Schreiben in pipe zu der kein Leser existiert oder Ablauf von Wecker (SIGALRM) in /usr/include/linux/signal.h sind Namen aller signale aufgelistet.

Einschub: Info GL: Funktionspointer Man kann einer Funktion eine andere Funkt. als Parameter mit call by refrc übergeben für generische Programme zuerst Typ für Header deklariern typedef int cmp(int x,int y); –Funktion hat zwei int als Parameter und gibt int zurück

Funktionspointer typedef int cmp(int x,int y); Extremus(cmp *cmpFunc; int mAr[LENGTH] { int ret; int extr = mAr[0]; for (i=1; i <LENGTH; i++) if (cmp(mAr[i],extr) == 0) ret = mAr[i]; return ret; } main() { ret =Extremus(min,mAr[LENGTH]); printf (“min %d”,ret); ret=Extremus( max,mAr[LENGTH]); printf (“max %d”,ret); int min(int x,int y) { if (x<y) return 0 else return 1; } int max(int x,int y) { if (x>y) return 0 else return 1; }

Signalkonzept Da Signale asynchron auftreten (man weiss nicht, wann Signal auftritt), kann man nicht Variable verwenden um Wert von signal abzufragen. Stattdessen: Einrichten eines Signalhandlers: Wenn bestimmtes Signal auftritt tue folgendes! Wenn bestimmtes Signal auftritt rufe Funktion auf! Angabe von Signalnummer und Funktion siehe Bild an Tafel void (*signal(int signr, void (*sighandler)(int)))(int); (nächste Folie einfacher!!)

Deklaration von signalhandler Vereinfachung durch typedef void sigfunk(int) statt void (*signal(int signr, void (*sighandler)(int)))(int); sigfunk *signal(int signr, sigfunk *sighandler); signr legt Nummer des Signals fest, für das man Signalhandler einrichtet. sighandler ist Funktion, die in Zukunft bei Auftreten von signr aufgerufen wird. Rückgabewert ist bisheriger sighandler oder SIG_ERR

Bsp: Abfangen von Signal für Division durch Null #include static void null_division(int sig); main () if (signal(SIGFPE,null_division) == SIG_ERR) printf(„signalhandler konnte nicht eingerichtet werden“); // Ab híer wird null_division aufgerufen wenn Signal gesendet! } void null_division(int sig) { // Für Dauer der Funktion müssen weitere SIGFPE ignoriert werden! signal(SIGFPE, SIG_IGN); printf(„division durch null“); }

sighandler Signal ignorieren (SIG_IGN): für alle signale auuser SIGKILL und SIGSTOP möglich. Achtung: ignorieren von „ernstzunehmenden“ signalen wie SIGSEGV kann zu Absturz führen Default-Aktion einrichten (SIG_DFL): für meisten Signale ist default Beendigung von Prozess Pointer auf Funktion, die aufzurufen ist, wenn Signal signr auftritt: –Meistens selbstgeschriebene Funktion.

SignalbehandlungsFunktionen –z.b. cleanup() wird aufgerufen, wenn Abbruchsignal geschickt. cleanup gibt Speicher frei, schliesst Dateien –z.b. Abfangen des Signals SIGCHLD, das bei Beendigung von Kindprozess an Vater gesendet wird. Hier sollte Vater waitpid aufrufen, um Zombie zu vermeiden.

Senden von Signal: kill int kill (pid_t pid,int signr); pid > 0 Signal signr wird an Prozess mit PID pid geschickt. ( pid < -1 Signal an ProzessgruppenID gleich |pid|) pid == -1: Broadcast Signale. An alle Prozesse int raise(int signr) schickt signal an sich selber

Probleme mit der signal Funktion Signalkonzept ist unzuverlässig: Erfragen des aktuellen Signalstatus ohne Änderung nicht möglich: if (sighandler=signal(SIGINT, SIG_IGN) !=SIG_IGN) signal(SIGINT,sighandler); Nach dem Abfragen des Signals wird automatisch die Default Aktion vom System eingerichtet

Problem: automatisch Default Aktion eingerichtet main {..... signal(SIGINT, sighandler) } int signalhandler { //kritische Stelle signal(SIGINT,sighandler);..... } Wenn bei krit. Stelle erneut SIGINT gesendet wird, wird default Aktion ausgeführt! Kommt allerdings selten vor (kurze Zeit in krit.Stelle). -> in Testphase unwahrscheinl. aber eventuell in produktivem Einsatz!

Probleme mit der signal Funktion cont‘ Man kann nicht Signal kurzzeitig blockieren, um es später zu bearbeiten. Möglichkeit: ignorieren. Dann weiss man nicht ob in Zwischenzeit Signal aufgetreten ist! Andere Mögl: sighandler tut nichts ausser globales flag zu setzten. Kann später abgefragt werden.

int sigint_flag =0; main {..... signal(SIGINT, sighandler ) // Prozess kann weiterarbeiten while (sigint_flag==0) //kritische Stelle pause(); } int signalhandler { sigint_flag=1; } Wenn bei krit. Stelle SIGINT gesendet wird, ist Signal verloren! Endlosschleife! Probleme mit der signal Funktion cont‘

Lösung der Probleme neues Signalkonzept Signalmengen sigaction() Signalmasken

Zeitschaltuhr int alarm(int seconds); wenn seconds abgelaufen sind, wird Signal SIGALRM gesendet. Wenn bei alarm-Aufruf eingeschaltete Uhr noch nicht abgelaufen ist wird diese durch neue ersetzt. Rückgabewert ist dann verbleibende Zeit Mit seconds =0 kann Wecker abgeschaltet werden. Typische Anwendung: Festlegen einer oberen Zeitgrenze für Aktionen die blockiert werden können (z.b. Lesen von Netzwerk)

IPC InterProcessCommunication Damit Prozess untereinander kommunizieren können gibt es verschiedene Mechanismen: –shared file (ineffizient!) –Pipes –FIFOs (named Pipes) –Stream Pipes –Message Queues –Semaphore –Shared Memory –Sockets –STREAMS

Pipes (Einschränkungen) 1.Pipes können nur zwischen Prozessen eingerichtet werdn die gemeinsame Vorfahren =(Gross)Eltern haben. –Normalerweise wird pipe von Elternprozess eingerichtet der dann mit fork() Kind kreirt, der dann pipe erbt 2.pipes sind halbduplex, d.h. Daten können immer nur in eine Richtung fliessen. –Prozess der Pipe zum Schreiben eingerichtet hat kann nicht aus pipe lesen (nur Prozess auf anderen Seite kann das) –Will man Duplex-Kommunikation braucht man 2 pipes

FIFOS und Stream Pipes FIFOS haben Einschränkung 1 nicht. Können also zwischen beliebigen Prozessen eingerichtet werden Stream Pipes haben Einschränkung 2 nicht. Sind also vollduplex. FIFOS bzw. Stream Pipes nur auf bestimmten UNIX-Derivaten!

Einrichten einer pipe int pipe(int fd[2]); fd[0] liefert Filedeskriptor zum Lesen aus pipe fd[1] liefert Filedeskriptor zum Schreiben in pipe fd[0]fd[1] Prozess A Kern

Pipe nach fork-Aufruf fd[0]fd[1] ElternProzess A Kern fd[0]fd[1] KindProzess A Normalerweise ruft man nach pipe fork auf, damit man mit Kind über pipe kommunizieren kann.

Elternprozess schreibt und Kind liest close(fd[0])fd[1] ElternProzess A Kern fd[0]close (fd[1]) KindProzess A Elternprozess schliesst Leseseite der pipe und Kindprozess Schreibseite der Pipe

Schliessen einer Seite Nach Schliessen einer Seite gelten folgende Regeln: Lesen aus Pipe, deren Schreibseite geschlossen wurde, nachdem alle Daten aus Pipe gelesen wurde, liefert read() 0 (für EOF). Schreiben in Pipe deren Leseseite geschlossen, liefert SIGPIPE. Sowohl beim Ignoriern als auch Abfangen des Signals (nach Rückkehr aus Signalhandler) liefert write Fehler.

Kommunikation von nicht verwandten Prozessen Da alle IPC Objekte ausser pipe auch zwischen nicht verwandten Prozessen möglich braucht man Kennungen (IDs) ID: wird vom System vergeben (wie PID), Schlüssel (key) wird vom Programmierer vergeben: –Wenn neues Objekt angelegt wird key angegeben. –Angabe von IPC_PRIVATE bewirkt anlegen von neuem Objekt

Kommunikation von nicht verwandten Prozessen Prozess A (Server) kreiert neues Objekt mit IPC_PRIVATE. Zurückgegebene Kennung wird an vereinbarte Stelle (z.b. Datei) gespeichert. Andere Prozess B,C.. (Clients) kann Kennung aus Datei lesen und mit Kennung auf IPC-Objekt zugreifen. Client und Server vereinbaren gemeinsamen Schlüssel (z.b. in header file). Server kreiert Objekt mit diesem key. Problem: key könnte schon vergeben sein.

Einrichten von neuem Objekt msgget, semget, shmgt int msgget(key_t key, int flag); –flag IPC_CREAT oder –IPC_EXCL: wenn Objekt mit key bereits existiert Fehlerrückgabe –Rückgabewert ist Kennung

Verbindung zu existierendem Objekt herstellen auch mit msgget(), jedoch IPC_CREAT nicht gesetzt! Anzeigen existierender IPC-Objekte und ihr Status: ipcs in Konsole/Shell Löschen mit ipcrm

message queues Nachrichtenwarteschlangen werden in Form von verketteten Liste vom System verwaltet Message besteht aus 3 Komponenten: –Message-Typ –Länge der Message ( size_t ) –Message-String

message queues Zum Senden von Nachricht: msgsnd() Zum Empfangen: msgrcv() Messages müssen nicht in der Reihenfolge gelesen werden in der sie gespeichert wurden! Durch Angabe von Typ in msgrcv() können messages „ausgelassen“ werden..

msgsnd int msgsnd(int id, const void *buffer, size_t length, int flag) size_t ist int oder long length legt Länge von Message-Text (buffer- sizeof(long) für Typ) fest id ist Kennung die von msgget zurückgegeben wurde buffer z.b. Zeiger auf struct my_msg { long mtype; char mtext[MAX] }

msgrcv() int msgrcv(int id, const void *buffer, size_t length, long type, int flag) length legt maximale Länge von Message-Text (buffer-sizeof(long) für Typ) fest. Fehler wenn msg grösser. type legt fest welche msg aus queue gelesen –type = 0: erste msg aus Queue (FIFO) –type > 0: 1. msg die den Typ type hat. –type < 0: 1.msg deren Typ kleinster wert ist der kleiner oder gleich absolut Betrag von type.

flag msgsnd blockiert normalerweise wenn queue voll. msgrcv blockiert wenn keine msg mit typ vorhanden. IPC_NOWAIT in flag: non-blocking function Sonst (bei Übung) flag=0 Verwendung von typ für Prioritäten Client-Server Anwendungen wenn nur eine msg queue zwischen client und server. PID kann als Typ zur Identifikation der clients verwendet werden.

Client Server Anwendungen Server stellt Dienst zur Verfügung. Clients können Dienst nutzen. Client sendet request(Anfrage) an Server Server bearbeitet und beantwortet request