Dateipufferung
In diesem Thema werden die verschiedenen Überlegungen zur Anwendungssteuerung der Dateipufferung behandelt, die auch als ungepufferte Dateieingabe/-ausgabe (E/A) bezeichnet wird. Die Dateipufferung wird normalerweise im Hintergrund vom System verarbeitet und wird als Teil der Dateizwischenspeicherung innerhalb des Windows-Betriebssystems betrachtet, sofern nichts anderes angegeben ist. Obwohl die Begriffe Zwischenspeichern und Puffern manchmal synonym verwendet werden, wird in diesem Thema der Begriff Pufferung speziell im Kontext der Erläuterung der Interaktion mit Daten verwendet, die nicht vom System zwischengespeichert (gepuffert) werden, wo sie ansonsten größtenteils nicht der direkten Kontrolle von Benutzermodusanwendungen unterliegen.
Beim Öffnen oder Erstellen einer Datei mit der CreateFile-Funktion kann das FILE_FLAG_NO_BUFFERING-Flag angegeben werden, um die Systemzwischenspeicherung von Daten zu deaktivieren, die aus der Datei gelesen oder in die Datei geschrieben werden. Dies ermöglicht zwar eine vollständige und direkte Kontrolle über die Daten-E/A-Pufferung, aber bei Dateien und ähnlichen Geräten müssen Anforderungen an die Datenausrichtung berücksichtigt werden.
Hinweis
Diese Ausrichtungsinformationen gelten für E/A-Geräte, z. B. Dateien, die die Suche unterstützen, und das Konzept von Dateipositionszeigern (oder Offsets). Für Geräte, die nicht gesucht werden, z. B. Named Pipes oder Kommunikationsgeräte, erfordert das Deaktivieren der Pufferung möglicherweise keine bestimmte Ausrichtung. Alle Einschränkungen oder Effizienzen, die in diesem Fall durch die Ausrichtung gewonnen werden können, hängen von der zugrunde liegenden Technologie ab.
In einem einfachen Beispiel öffnet die Anwendung eine Datei für den Schreibzugriff mit dem flag FILE_FLAG_NO_BUFFERING und führt dann einen Aufruf der WriteFile-Funktion mithilfe eines in der Anwendung definierten Datenpuffers aus. Dieser lokale Puffer ist unter diesen Umständen der einzige Dateipuffer, der für diesen Vorgang vorhanden ist. Aufgrund des Layouts des physischen Datenträgers, des Dateisystemspeicherlayouts und der Nachverfolgung der Position auf Dateizeiger auf Systemebene schlägt dieser Schreibvorgang fehl, es sei denn, die lokal definierten Datenpuffer erfüllen bestimmte Ausrichtungskriterien, die im folgenden Abschnitt erläutert werden.
Hinweis
Die Diskussion über das Zwischenspeichern berücksichtigt keine Hardwarezwischenspeicherung auf dem physischen Datenträger selbst, die in keinem Fall innerhalb der direkten Kontrolle des Systems liegt. Dies hat keine Auswirkungen auf die in diesem Thema angegebenen Anforderungen.
Weitere Informationen dazu, wie FILE_FLAG_NO_BUFFERING mit anderen cachebezogenen Flags interagiert, finden Sie unter CreateFile.
Ausrichtungs- und Dateizugriffsanforderungen
Wie bereits erwähnt, muss eine Anwendung bestimmte Anforderungen erfüllen, wenn sie mit Dateien arbeitet, die mit FILE_FLAG_NO_BUFFERING geöffnet wurden. Es gelten die folgenden Besonderheiten:
- Dateizugriffsgrößen, einschließlich des optionalen Dateioffsets in der OVERLAPPED-Struktur , sofern angegeben, müssen für eine Anzahl von Bytes gelten, die ein ganzzahliges Vielfaches der Größe des Volumesektors ist. Wenn die Sektorgröße beispielsweise 512 Bytes beträgt, kann eine Anwendung Lese- und Schreibvorgänge von 512, 1.024, 1.536 oder 2.048 Bytes anfordern, jedoch nicht von 335, 981 oder 7.171 Bytes.
- Die Dateizugriffspufferadressen für Lese- und Schreibvorgänge sollten auf den physischen Sektor ausgerichtet sein. Dies bedeutet, dass sie an Adressen im Arbeitsspeicher ausgerichtet sind, die ganzzahlige Vielfache der physischen Sektorgröße des Volumes darstellen. Je nach Datenträger wird diese Anforderung möglicherweise nicht erzwungen.
Anwendungsentwickler sollten beachten, dass neue Arten von Speichergeräten mit einer Größe des physischen Mediensektors von 4.096 Bytes auf den Markt eingeführt werden. Der Branchenname für diese Geräte lautet "Advanced Format". Da kompatibilitätsprobleme bei der direkten Einführung von 4.096 Byte als Adressierungseinheit für die Medien auftreten können, besteht eine temporäre Kompatibilitätslösung darin, Geräte einzuführen, die ein reguläres Speichergerät mit 512 Byte-Sektor emulieren, aber Mithilfe von Ata- und SCSI-Standardbefehlen Informationen zur tatsächlichen Sektorgröße verfügbar machen.
Als Ergebnis dieser Emulation gibt es im Wesentlichen zwei Sektorgrößen, die Entwickler verstehen müssen:
- Logischer Sektor: Die Einheit, die für die logische Blockadressierung für die Medien verwendet wird. Wir können uns dies auch als die kleinste Schreibeinheit vorstellen, die der Speicher akzeptieren kann. Dies ist die "Emulation".
- Physischer Sektor: Die Einheit, für die Lese- und Schreibvorgänge auf dem Gerät in einem einzigen Vorgang ausgeführt werden. Dies ist die Einheit des atomaren Schreibens, an der ungepufferte E/A ausgerichtet werden muss, um optimale Leistungs- und Zuverlässigkeitsmerkmale zu erhalten.
Die meisten aktuellen Windows-APIs, z. B. IOCTL_DISK_GET_DRIVE_GEOMETRY und GetDiskFreeSpace, geben die logische Sektorgröße zurück, aber die größe des physischen Sektors kann über den IOCTL_STORAGE_QUERY_PROPERTY-Steuerungscode abgerufen werden, wobei die relevanten Informationen im BytesPerPhysicalSector-Element in der STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR-Struktur enthalten sind. Ein Beispiel finden Sie im Beispielcode unter STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR. Microsoft empfiehlt Entwicklern dringend, nicht gepufferte E/A-Vorgänge an die größe des physischen Sektors auszurichten, wie im IOCTL_STORAGE_QUERY_PROPERTY-Kontrollcode angegeben, um sicherzustellen, dass ihre Anwendungen für diesen Sektorgrößenübergang vorbereitet sind.
Windows Server 2003 und Windows XP: Die STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR-Struktur ist nicht verfügbar. Es wurde mit Windows Vista und Windows Server 2008 eingeführt.
Da Pufferadressen für Lese- und Schreibvorgänge sektoral ausgerichtet sein müssen, muss die Anwendung direkt steuern, wie diese Puffer zugeordnet werden. Eine Möglichkeit zum Ausrichten von Puffern in Sektoren besteht darin, die VirtualAlloc-Funktion zum Zuordnen der Puffer zu verwenden. Beachten Sie Folgendes:
- VirtualAlloc weist Arbeitsspeicher zu, der an Adressen ausgerichtet ist, die ganzzahlige Vielfache der Seitengröße des Systems sind. Die Seitengröße beträgt 4.096 Bytes unter x64 und x86 oder 8.192 Bytes für Itanium-basierte Systeme. Weitere Informationen finden Sie in der GetSystemInfo-Funktion .
- Die Sektorgröße beträgt in der Regel 512 bis 4.096 Bytes für Speichergeräte mit direktem Zugriff (Festplatten) und 2.048 Bytes für CD-ROMs.
- Sowohl seiten- als auch sektorspezifische Größen sind Potenzen von 2.
Daher wird in den meisten Situationen seitenorientierter Speicher auch sektorseitig ausgerichtet, da die Sektorgröße selten größer als die Seitengröße ist.
Eine weitere Möglichkeit zum Abrufen manuell ausgerichteter Speicherpuffer besteht darin, die funktion _aligned_malloc aus der C-Run-Time bibliothek zu verwenden. Ein Beispiel für die manuelle Steuerung der Pufferausrichtung finden Sie im C++-Sprachcodebeispiel im Abschnitt Beispielcode von WriteFile.