bs-6.5

Werbung
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
Herunterladen