PROGRAMMIEREN MIT UNIX/LINUX-SYSTEMAUFRUFEN 3. UNIX/Linux-Dateisysteme und zugehörige Systemaufrufe und Kommandos (Teil I) Wintersemester 206/7
UNIX/Linux-Dateisystem(e) Systemaufrufe zur Dateiarbeit: creat(...) Erzeugen einer neuen Datei open(...) close(...) Öffnen einer bereits existierenden Datei (auch bei entsprechenden Parameterangaben: erzeugen einer neuen Datei) schließen einer Datei (nach Beendigung der Dateiarbeit) read(...) write(...) Lesen aus einer Datei Schreiben in eine Datei lseek(...) Einstellen des Lese-/Schreibzeigers einer Datei ws 206/7 H.-A. Schindler Folie: 3-2
Organisation einer Festplatte unter UNIX Dateiblöcke (Boot- Block) Superblock i-nodes Metadaten Indexblock Zugriffsrechte Link-Zähler uid gid Datei-Länge Adressen der ersten 0 direktenblöcke Einfach Indirekt Zweifach Indirekt Dreifach Indirekt Darstellung nach /Nehmer+98/ Bild 9-2 S.279 ws 206/7 H.-A. Schindler Folie: 3-3
Verwaltungsstruktur inode inodes existieren als statische Strukturen zunächst auf Festplatte. ein Datenträger-inode enthält folgende Komponenten: Eigentümer und Gruppe des Eigentümers Zugriffsrechte( rwx jeweils für: Eigentümer / Gruppe / andere), Typ der Datei (regulär / Verzeichnis / Pipe /...) Zeitpunkt der letzten Dateiänderung Zeitpunkt des letzten Dateizugriffs Zeitpunkt der letzten Änderung dieses inodes Anzahl der Links auf zugehörige Datei Dateilänge (in Byte) Blocknummern der Dateiblöcke - 0 Adressen auf direkte Dateiblöcke - Adresse auf einfach-indirekten Block - Adresse auf doppelt-indirekten Block - Adresse auf dreifach-indirekten Block ws 206/7 H.-A. Schindler Folie: 3-4
UNIX/LINUX-Dateien: Gestreute Speicherung der Dateiblöcke Block-Nummerierung auf Datenträger 4 5 Beginn der Datei 3 EOF (end of file) [Dateiende] Nummerierung der Blöcke innerhalb einer Datei 34 2 Verkettung Vorteile: Editier-Operationen effizient implementierbar Nachteile: serielles Lesen nicht zeiteffizient größere Gleichlaufschwankungen (Jitter) beim Auslesen ws 206/7 H.-A. Schindler Folie: 3-5
Gestreute Speicherung: Verkettung über Indexblock (Prinzip) Datei-Name Index-Block Datei 9 Datei2... Verzeichnis - (Directory) Ausschnitt 0 2 3 4 5 6 7 8 9 0 2 3 4 5 6 7 8 9 20 2 22 23 9 9 6 0 25 - - - nicht belegt = EOF 24 25 26 27 28 29 30 3 Inhalt des Indexblocks Darstellung nach /Silberschatz+9/ Bild 9.6 S.343 ws 206/7 H.-A. Schindler Folie: 3-6
echte Datenblöcke UNIX/LINUX: Indirekte Adressierung von Dateiblöcken Datei-Name inode-nr. Datei 00 Datei2... Verzeichnis- Ausschnitt.................... Sekundäre usw. Indexblöcke (Benutzung abhängig von Datei-Länge) Datei- Attribute direkt(0) direkt() direkt(2) direkt(3) direkt(4) direkt(5) direkt(6) direkt(7) direkt(8) direkt(9) einfach indirekt doppelt indirekt dreifach indirekt Index-Block (innerhalb eines inode) Darstellung nach /Inf-Handbuch/ Bild S.542 ws 206/7 H.-A. Schindler Folie: 3-7
Systemaufruf creat(..) erzeugt neue Datei Verwendung im Programm (Prinzip): int <id_file>; I <id_file> = creat( <pathname>, <mode>); Konkretes Beispiel: int fd; I fd = creat( NeueDatei, 0700); <id_file> int >=3 Identifikator(Nummer) einer von einem bestimmten Prozess geöffneten Datei (Eintrag in der ufd-struktur des Prozeskontrollblocks) - Systemaufruf fehlgeschlagen <pathname> <mode> int Pfadname der Datei, ausgehend vom aktuellen Verzeichnis bzw. absolut Zugriffsrechte auf neue Datei (Angabe als Oktalzahl: z.b. 0770 = rwxrwx---) folgende Folien ws 206/7 H.-A. Schindler Folie: 3-8
Programm creat.c main() { } int fd; fd= creat("neuedatei", 0700); /* 0700: Zugriffsrechte (oktal): rwx------*/ ws 206/7 H.-A. Schindler Folie: 3-9
UNIX/Linux-Zugriffsrechte ( Permissions ) Bei UNIX-Systemen basieren Zugriffsrechteauf verschiedenste Objekte (z.b. Dateien, diverse Kontrollblöcke, Message-Queues usw.) auf einem Eigentümer/Nutzergruppen-Konzept Jedes derartige Objekt hat einen Eigentümer, der einer bestimmten Nutzer- Gruppe (ggf. auch mehreren) angehört. Als mögliche Zugriffsarten sind definiert: Lesen: r ( read ) Schreiben: w ( write) Ausführen: x ( execute ) Zugriffsrechte werden dann gesondert in der Reihenfolge: Eigentümer Gruppe alle anderen Nutzer ( world ) an diese vergeben (und können durch den Eigentümer auch geändert werden). ws 206/7 H.-A. Schindler Folie: 3-0
Symbolische Darstellung der Zugriffsrechte Bei Darstellungen wird ein gesetztes Recht durch das jeweilige Zeichen r, w oder x symbolisiert ein nicht gesetztes durch einen Strich. (vergleiche z.b. die Ausgabe des Kommandos ls l?, welches u.a. die für die jeweils betrachteten Dateien die Zugriffsrechte ausgibt.) Beispiele:.) r w x r r bei einer Datei: Eigentümer: darf Datei lesen, schreiben (d.h. Ändern oder Löschen) und ausführen (sinnvoll natürlich nur bei ausführbaren Dateien) Mitglieder der Gruppe: nur Lesen erlaubt alle Anderen: gleichfalls nur Lesen erlaubt 2.) r w x r x x bei einer Datei: Eigentümer: darf Datei lesen, schreiben und ausführen Mitglieder der Gruppe: dürfen lesen und ausführen alle Anderen: dürfen nur Ausführen ws 206/7 H.-A. Schindler Folie: 3 -
Symbolische Darstellung der Zugriffsrechte binäre Darstellung: gesetzte Rechte werden als L (= ) interpretiert, nicht gesetzte als 0 (Null) Beispiele:.) r w x r r 0000 2.) r w x r x x 000 Darstellung als Oktalzahl: jeweils 3 Rechte zusammengefasst: Beispiele:.) r w x r r 0000 07 2.) r w x r x r 000 0754 ws 206/7 H.-A. Schindler Folie: 3-2
Öffnen von Dateien: Systemaufruf open(... ) Bevor Lese- oder Schreibzugriffe auf eine (existierende) Datei ausgeführt werden können, muss diese (durch jeweiligen Prozess) geöffnet werden. Warum? Zugriff auf Festplatte: wesentlich langsamer als Hauptspeicherzugriff Geschwindigkeitssteigerung: so wenig Plattenzugriffe, wie möglich:. Nur einmal Durchhangeln durch Verzeichnisstruktur, dann Zugriff über Identifikator id_file 2. Verwaltungsstrukturen für Festplatte ( Superblock ) u. Datei ( inode ) in Hauptspeicher geladen durch open(..) oder creat(..) veranlasst [nach Änderung Zurückschreiben nötig!! sync()] 3. Lesen u. Schreiben von Dateiblöcken über Dateicache im Hauptspeicher ws 206/7 H.-A. Schindler Folie: 3-3
open(... ) öffnet existierende Datei oder erzeugt neue Datei Verwendung im Programm (Prinzip): int <id_file>; I <id_file> = open( <pathname>, <mode> ); Konkretes Beispiel: int fd; I fd = open( NeueDatei, 2); <id_file> int wie bei creat(..) <pathname> wie bei creat(..) <mode> int anders als bei creat: O_RDONLY (= 0)... nur zum Lesen öffnen O_WRONLY (= )... nur zum Schreiben öffnen O_RDWR (= 2)... zum Lesen und Schreiben öffnen (weitere Angaben möglich, siehe Literatur) ws 206/7 H.-A. Schindler Folie: 3-4
Daten-Strukturen im HS für unmittelbare Dateizugriffe nach open(..) user file descriptor table (in User-Struktur des PCB) 0 2 3 4 5 6 7 file table Read 2 inode table (/etc/passwd) Rd-Wrt (local) id_file_ = open( /etc/passwd, O_RDONLY); id_file_2 = open( local, O_RDWR); id_file_3 = open( /etc/passwd, O_WRONLY); Write (im Adressbereich des Betriebssystemkerns) Darstellung nach /Bach86/ Bild 5.3 S. 94 ws 206/7 H.-A. Schindler Folie: 3-5
Daten-Strukturen nachdem 2 Prozesse Dateien geöffnet haben user file descriptor table (Prozess ) 0 2 3 4 5 6 0 2 3 4 5 6 7 file table 7 Read Rd-Wrt Read 3 inode table (/etc/passwd) (local) (Prozess 2) id_file_4 = open( /etc/passwd, O_RDONLY); id_file_5 = open( private, O_RDONLY); Write Read (private) (im Adressbereich des Betriebssystemkerns) Darstellung nach /Bach86/ Bild 5.4 S. 95 ws 206/7 H.-A. Schindler Folie: 3-6
Systemaufruf close(...) schließt(zuvor geöffnete oder erzeugte) Datei Aufruf im Programmtext: <result> = close(<id_file>); <result> int 0: fehlerfreie Ausführung -: Systemaufruf fehlgeschlagen <id_file> int Rückkehrwert bei open(..) bzw. creat(..), siehe dort ws 206/7 H.-A. Schindler Folie: 3-7
Daten-Strukturen nachdem Prozess Datei wieder geschlossen hat user file descriptor table (Prozess ) 0 2 3 4 5 6 NULL 0 2 3 4 5 6 7 file table 7 Read Rd-Wrt Read 3 inode table (/etc/passwd) (local) (Prozess 2) Write result = close(id_file_5); (im Adressbereich des Betriebssystemkerns) Darstellung nach /Bach86/ Bild 5. S. 05 ws 206/7 H.-A. Schindler Folie: 3-8
Systemaufruf read(...) liest aus(zuvor geöffneter) Datei Aufruf im Programmtext: <rbyte> = read(<id_file>, <address>, <nbyte>); <rbyte> int Anzahl der tatsächlich gelesenen Byte <id_file> int Rückkehrwert von open(..), siehe dort <address> int Adresse im Programm, ab der die aus der Datei gelesenen Daten unterzubringen sind <nbyte> int Anzahl der Byte, die gelesen werden sollen ws 206/7 H.-A. Schindler Folie: 3-9
Programm openread.c #include <stdio.h> main() { int i, fd, rbytes; char buffer[000]; // Puffer vorab "saeubern" for(i = 0; i < 000; i++) buffer[i] = '\0'; fd= open("./openread.c", 0); rbytes = read(fd, buffer, 000); } printf("\n\ninterne Datei-Nr:%d\n\nGELESENE ZEICHEN: \ Anzahl:%d\nTEXT:\n\n%00s\n\n", fd, rbytes, buffer); ws 206/7 H.-A. Schindler Folie: 3-20
Systemaufruf write(...) schreibt in(zuvor geöffnete bzw. erzeugte) Datei Aufruf im Programmtext: <wbyte> = write(<id_file>, <address>, <nbyte>); <wbyte> int Anzahl der tatsächlich geschriebenen Byte <id_file> int Rückkehrwert von open(..) bzw. creat(..), siehe dort <address> int Anfangsadresse eines Programmbereichs, ab der in die Datei zu schreibende Daten stehen <nbyte> int Anzahl der Byte, die geschrieben werden sollen ws 206/7 H.-A. Schindler Folie: 3-2
Programm openwrite.c char buffer[] = "Dieser Text soll in die Datei "; main() { } int fd, wbytes; fd= open("neuedatei", 2); wbytes = write(fd, buffer, 29); ws 206/7 H.-A. Schindler Folie: 3-22
Systemaufruf lseek(...) stellt Lese-/Schreibzeiger einer(zuvor geöffneten) Datei ein Aufruf im Programmtext: <position> = lseek(<id_file>, <offset>, <reference>); <position> long eingestellte Position <id_file> int Rückkehrwert von open(..), siehe dort <offset> long Größe der Änderung des aktuellen Zeigerwerts <reference> int Bezugspunkt, auf den sich offset bezieht SEEK_SET... Dateianfang SEEK_CUR... aktueller Zeigerwert SEEK_END... Dateiende ws 206/7 H.-A. Schindler Folie: 3-23
Zusammenhänge <address> Daten- Bereich read(..) write(..) <position> Lese-/Schreibzeiger Einstellung: lseek(..) Prozess (Programm) Datei (auf Festplatte) ohne Berücksichtigung einzelner Blöcke ws 206/7 H.-A. Schindler Folie: 3-24
Realisierung der Read- und Write-Funktionen über Dateipuffer inode Dateizeiger im Hauptspeicher Dateipuffer Pufferposition Ortsinformation Externer Speicher (Festplatte) Darstellung nach /Nehmer+98/ Bild 9-2 S.263 ws 206/7 H.-A. Schindler Folie: 3-25
Kommandos und #include-dateien Anzeigen von i-node-informationen: Kommando ls ( list Iauflisten) mit Parameter l ( long ): ls l <name> wird größte Informationsmenge geliefert zur Arbeit mit Dateien werden benötigt: #include <stdio.h> // zur Ausführung von E/A-Operationen [meist printf(...)] #include <sys/types.h> // wegen Definitionen spezieller Datentypen #include <fcntl.h> // spezielle Definitionen zu Dateien ws 206/7 H.-A. Schindler Folie: 3-26
Aufgabenstellung. Verwenden Sie Beispielprogramm creat.c welches eine neue Datei im aktuellen Verzeichnis erzeugt. Überprüfen Sie, ob nach einer Ausführung des übersetzten Programms die gewünschte Datei existiert, welche Länge und welchen Inhalt sie hat und ob die spezifizierten Zugriffsrechte gesetzt sind. (Verwenden Sie u.a. das UNIX-Kommando ls l.) Sie können mit geänderten Zugriffsrechten und z.b. absoluten Pfadnamen weiter experimentieren. Überprüfen Sie auch, ob ein spezifizierter aber nicht existierender Pfad eingerichtet wird. 2. Verwenden Sie jetzt Programm openwrite.c welches in die erzeugte Datei schreibt. Kontrollieren Sie, ob es korrekt arbeitet. Sie können dann z.b. mit geänderten Textlängen, mehrmaligem Schreiben etc. weiter experimentieren. 3. Verwenden Sie jetzt Programm openread.c welches die eigene Quelltext-Datei liest. Kontrollieren Sie, ob es korrekt arbeitet. Interpretieren Sie den Rückgabewert von read(..). ws 206/7 H.-A. Schindler Folie: 3-27
Aufgabenstellung 4. Integrieren Sie in das Beispielprogramm openread.c den Systemaufruf lseek(..). Stellen Sie den Lese-/Schreibzeiger so ein, dass Sie nicht (wie ohne lseek(..)) ab Position 0 lesen, sondern z.b. erst ab Position 20 von Beginn, 30 von Dateiende usw. Untersuchen Sie jeweils auch die Rückkehrwerte der Systemaufrufe. ENDE 3 ws 206/7 H.-A. Schindler Folie: 3-28