6.5 Dateien als Segmente Idee: Datei = persistentes Segment Konsequenzen: Datei kann in virtuellen Adressraum eingeblendet werden (memory-mapped file) keine spezielle Ein/Ausgabe für Dateien, kein Blockpuffer Geschichte: reicht zurück bis MULTICS (M.I.T. 1965-70) bs-6.5 1 6.5.1 Programmladen über Seitenfehler (demand-paged program loading) Code-Teil der Programmdatei wird wie Code-Segment im Sekundärspeicher behandelt: exec richtet Segmentstruktur des Prozesses ein (wie üblich), überträgt aber keinen Code in den Primär- oder Sekundärspeicher. In Unix erstmalig mit Version System V, heute bei den meisten Betriebssystemen üblich. bs-6.5 2 Ablauf: 1. exec: Segmente des Prozesses einrichten (gemäß Beschreibung in Programmdatei) : • Datei aktivieren: reqDesc liefert dno • • dno im Deskriptor des Code-Segments notieren (für Nicht-Code-Segmente ist dieses Feld 0) Seitendeskriptoren einrichten: - spezielle Markierung „von Datei einlagern“ - Blocknummer innerhalb der Datei 2. Ausgezeichnete Startseite einlagern und starten 3. Bei Bedarf – gesteuert durch Seitenfehler – Rahmen für einzelne Seite finden und Codeseite einlagern 4. Verdrängen erfolgt ohne physisches Kopieren bs-6.5 3 6.5.2 Dynamisches Binden (dynamic link libraries, DLLs, shared libraries) Varianten für das Einbinden von vorübersetzten Prozeduren, Modulen, Klassen etc. aus Bibliotheken: statisch: nach der Übersetzung, vor dem Laden; zur Ladezeit gemäß Angaben in Programmdatei: entsprechende Segmente einrichten bzw. mitbenutzen; zur Laufzeit bei Bedarf – „dynamisch“. bs-6.5 4 Binder (linker, linkage editor) entnimmt Code aus Bibliothek und fügt ihn mit dem anderen Code zusammen (mit Adressverschiebung und Auflösung externer Bezugnahmen); kein Sharing! Bindender Lader (linking loader) bindet beim Laden und berücksichtigt dabei Codesegmente, die bereits von anderen Prozessen benutzt werden (Sharing); Achtung: Adressierungsproblem, wenn nicht jeder Code einem bestimmten (virtuellen) Segment zugeordnet ist! Das tatsächliche Laden der Codesegmente erfolgt seitenweise bedarfsgesteuert, wie in 6.5.1 skizziert, also nicht durch den Lader. bs-6.5 5 Vertreterroutinen (stubs) für externe Prozeduren werden statisch eingebunden; sie veranlassen beim jeweils ersten Aufruf Segmenterzeugung bzw. -anbindung sowie entsprechende Aufrufumlenkung; die Bereitstellung des Codesegments erfolgt durch einen speziellen Systemaufruf (6.5.3). bs-6.5 6 6.5.3 Einblenden beliebiger Dateien (memory-mapped files) mittels geeigneter Systemaufrufe erübrigt Blockpuffer (und damit Kopiervorgang!) erübrigt Systemaufrufe read, write, seek erübrigt eigenen Mechanismus für dynamisches Binden erübrigt eigenen Mechanismus für Sharing (5.4.3) bs-6.5 7 6.5.3.1 ... ohne Capabilities addr = open(name,mode) (Segment/Datei einblenden) etabliert die Datei als Segment (falls nicht schon geschehen), d.h. richtet Segmentdeskriptor und Seitentabelle ein; blendet das Segment an geeigneter Stelle in den Adressraum ein und liefert die Adresse der ersten Zelle. Danach z.B. x = addr[0]; ... x = addr[37]; ... close(addr); bs-6.5 Zugriff auf erste Zelle Segment wird ausgeblendet, ggfls. in Datei zurückkopiert 8 Beispiel Kopieren einer Datei: cp src dst ... from = open(src, READING); stat(src,attr); length1 = attr.st_size; to = open(dst,WRITING); stat(dst,attr); length2 = attr.st_size; if(length2 == 0) for(int i=0; i<length1; i++) to[i] = from[i]; close(from); close(to); bs-6.5 9 Bemerkungen: read, write, seek als einfache Bibliotheksroutinen Semantik eines weiteren open? (Datei über 2 virtuelle Segmente erreichbar??) Ausnutzung in höheren Programmiersprachen: benutzerdefinierte Dateitypen möglich – und damit persistente Objekte. bs-6.5 10 6.5.3.2 ... mit Capabilities cap = lookup(name,mode) * etabliert die Datei als Segment (falls nicht schon geschehen), d.h. richtet Segmentdeskriptor und Seitentabelle ein, und liefert eine Berechtigung für dieses Segment (vgl. 6.5.3.1). bs-6.5 11 addr = map(cap) blendet das mit cap identifizierte Segment an geeigneter Stelle in den Adressraum ein und liefert die Adresse der ersten Zelle (vgl. 6.5.3.1). unmap(addr) blendet das Segment wieder aus bs-6.5 12 Ähnlich in POSIX, Solaris, Linux, ...: fildes = open(...); normales Öffnen einer Datei, fildes Berechtigung a = mmap(addr,length,prot,flags,fildes,offset) blendet Datei in den Adressraum ein und liefert Adresse der ersten Zelle *. prot ist NONE oder Kombination von R,W,X. flags erlaubt u.a. SHARED, PRIVATE (private Kopie) munmap(a,length) blendet wieder aus (bis length) bs-6.5 13 6.5.3.3 ... und in Windows Dateien sind – wie bei POSIX – sowohl normal als auch als memory-mapped files benutzbar Berechtigungen für „File-Mapping-Objekte“ ( Segmente) kommen zum Einsatz DLLs werden über diesen Mechanismus realisiert Gemeinsame Segmente sind nur über diesen Mechanismus möglich bs-6.5 14 fHandle = OpenFile(name,access,...) liefert open file handle fmHandle = CreateFileMapping( fHandle, wenn –1, Segment ohne Datei ... name) Segmentname liefert Berechtigung für Segment Für Sharing: statt Weitergabe des fmHandle auch fmHandle = OpenFileMapping(...,name) bs-6.5 15 addr = MapViewOfFile(fmHandle,...) blendet das Segment an geeigneter Stelle ein und liefert Adresse der ersten Zelle. ODER mit explizitem Adressenwunsch: addr = MapViewOfFileEx(fmHandle, ..., address) x = addr[0]; bs-6.5 usw. 16 UnmapViewOfFile(addr) Ausblenden des Segments CloseHandle(fmHandle) Berechtigung für Segment aufgeben CloseHandle(fHandle) Berechtigung für Dateiobjekt aufgeben bs-6.5 17