PROGRAMMIEREN MIT UNIX/LINUX-SYSTEMAUFRUFEN 10. UNIX/Linux: Reaktion auf Fehler Wintersemester 2016/17
Reaktion auf Fehler: Übersicht Systemaufrufe: 1. Rückkehrwert: in den meisten (aber nicht in allen!) Fällen wird bei Fehler -1 zurückgegeben 2. Fehlervariable errno (error nomer ): über die externe Systemvariable werden viele Fehler genauer spezifiziert (siehe Beispielprogramme) Fehler bei der Programmabarbeitung: 1. Signale: (siehe Abschnitt 10) Ein Teil der UNIX-Signale ist der Mitteilung von Fehlern an den ausführenden Prozess vorbehalten, der diese auswerten oder übergehen kann. hierzu gehören: Division durch Null, Gleitkommaüberlauf u.a. Fehler über exit() mitteilen: Ein Kindprozess kann seine Fehler über spezielle exits an den Elternprozess mitteilen. ws2016/17 H.-A. Schindler Folie: 10-2
UNIX-Systeme:Übliche Fehlerausgabe (Beispiel e1sys.c) #include <errno.h> #include void perror(const char *s); extern int errno; Wichtiges zur Fehlerauswertung mittels errno blau hervorgehoben main() { int rw_open; // Rueckkehrwert fuer open-systemaufruf errno = 0; // wird vom System nicht auf Null gesetzt (!!) // Fehler, wenn "Datei1" nicht existiert: rw_open = open("datei1", O_RDONLY); if(rw_open == -1){ perror("abc"); // abc : irgendein (hier: sinnloser) Text perror("oeffnen Datei1"); // sinnvollere Text-Verwendung } ws2016/17 H.-A. Schindler Folie: 10-3
#include-datei errno.h(beispiel) Die Header-Datei mit diesen Definitionen kann sich je nach System an unterschiedlichen Stellen befinden, z.b. in /usr/include/errno.h Teilweise unterscheiden sich die durch errno definierten Fehler in verschiedenen Systemen. Es können auch noch wesentlich mehr errno-werte spezifiziert sein. #define EPERM 1 /* Operation not permitted*/ #define ENOENT 2 /* No such file or directory*/ #define ESRCH 3 /* No such process*/ #define EINTR 4 /* Interrupted system call*/ #define EIO 5 /* I/O error*/ #define ENXIO 6 /* No such device or address*/ #define E2BIG 7 /* Argument list too long*/ #define ENOEXEC 8 /* Exec format error*/ #define EBADF 9 /* Bad file number*/ #define ECHILD 10 /* No child processes*/ #define EAGAIN 11 /* Try again*/ #define ENOMEM 12 /* Out of memory*/ #define EACCES 13 /* Permission denied*/ #define EFAULT 14 /* Bad address*/ #define ENOTBLK 15 /* Block device required*/ ws2016/17 H.-A. Schindler Folie: 10-4
#include-datei errno.h (Beispiel) #define EBUSY 16 /* Device or resource busy*/ #define EEXIST 17 /* File exists*/ #define EXDEV 18 /* Cross-device link */ #define ENODEV 19 /* No such device*/ #define ENOTDIR 20 /* Not a directory*/ #define EISDIR 21 /* Is a directory*/ #define EINVAL 22 /* Invalid argument*/ #define ENFILE 23 /* File table overflow*/ #define EMFILE 24 /* Too many open files*/ #define ENOTTY 25 /* Not a typewriter*/ #define ETXTBSY 26 /* Text file busy*/ #define EFBIG 27 /* File too large */ #define ENOSPC 28 /* No space left on device*/ #define ESPIPE 29 /* Illegal seek*/ #define EROFS 30 /* Read-only file system*/ #define EMLINK 31 /* Too many links */ #define EPIPE 32 /* Broken pipe*/ #define EDOM 33 /* Math argument out of domain of func*/ #define ERANGE 34 /* Math result not representable*/... ws2016/17 H.-A. Schindler Folie: 10-5
Fehlerausgabe mit Routine my_errorreport() #include <stdio.h> #include <sys/file.h> #include <errno.h> Wichtiges zur Fehlerauswertung mittels errno blau hervorgehoben extern int errno; main() { int rw_open; // Rueckkehrwert fuer open()-systemaufruf printf("\ntestprogramm\ngenauere Fehlerspezifikation mittels errno\n H ); errno= 0; // Wichtig! errno wird vom System nicht auf Null gesetzt } //Datei1 existiert nicht oder hat ungeeignete Zugriffsrechte rw_open= open("datei1", O_RDONLY); printf("(kontrolle: Rueckkehrwert open: %d errno: %d)\n\n", rw_open, errno); if(rw_open == -1){ // Fehler so noch nicht genau bestimmt printf("fehler bei open: "); my_errorreport(errno); // eigene Routine zur genaueren Auswertung }; ws2016/17 H.-A. Schindler Folie: 10-6
Eigene Fehlerauswerte-Routine my_errorreport (Ausschnitt) my_errorreport(n) int n; { switch(n) { case 0: printf("durch errno wird kein Fehler mitgeteilt"); case 1: printf("operation nicht erlaubt"); //EPERM case 2: printf("datei oder Verzeichnis existiert nicht"); //ENOENT case 3: printf("kein solcher Prozess"); //ESRCH case 4: printf("unterbrochener Systemaufruf"); //EINTR case 5: printf("fehler bei der Ein-/Ausgabe"); //EIO case 6:... ws2016/17 H.-A. Schindler Folie: 10-7
Aufgabenstellung (Anregungen) 1. Im Progamme1sys.cist die aktuelle vom System vorgesehene Ausgabe von Fehlermitteilungen mit perror() gezeigt. (HINWEIS: Diese Fehlerausgabe sieht in älteren Systemen etwas anders aus!) 2. Studieren Sie die Programme e2.cund e3.c. Beschäftigen Sie sich insbesondere mit den durch errno genauer spezifizierten Fehlern. 3. Kompilieren Sie Programm e2.c. Führen Sie das übersetzte Programm zunächst aus, ohne eine zu öffnende Datei zur Verfügung zu stellen. Welcher Fehler wird durch das System festgestellt? 4. Erzeugen Sie jetzt eine Datei Datei1, aber mit zum spezifizierten open()- Aufruf ungeeigneten Zugriffsrechten. (Dateierzeugung: z.b. >Datei1, read-recht für alle entziehen: chmod a-r Datei1 ) Welcher Fehler wird jetzt durch das System festgestellt? 5. Verwenden Sie jetzt das Programm e3.c. Aus einer Datei ohne Inhalt(bzw. einer zum read-aufruf zu kurzen Datei) soll gelesen werden. Welcher Fehler wird jetzt durch das System festgestellt? ws2016/17 H.-A. Schindler Folie: 10-8
Aufgabenstellung (Anregungen) 6. Einen weiteren möglichen Fehler bei der Datei-Arbeit enthält e4.c R (Dabei sollte bei Datei1 aber das Leserecht wieder gesetzt sein!) 7. Sie können weitere interessante Fehlerfälle erzeugen. Verwenden Sie die vorgestellten Mechanismen und z.b. Beispielprogramme aus vorangegangenen Lehrveranstaltungen. ws2016/17 H.-A. Schindler Folie: 10-9