Direct und synchronized I/O unter Linux

Aus Thomas-Krenn-Wiki
Zur Navigation springen Zur Suche springen
Hinweis: Bitte beachten Sie, dass dieser Artikel / diese Kategorie sich entweder auf ältere Software/Hardware Komponenten bezieht oder aus sonstigen Gründen nicht mehr gewartet wird.
Diese Seite wird nicht mehr aktualisiert und ist rein zu Referenzzwecken noch hier im Archiv abrufbar.

dd ermöglicht über die Angabe von iflag bzw. oflag Parametern diverse Optionen zum Lesen (iflag) sowie zum Schreiben (oflag) von Daten anzuführen. Die Parameter direct, dsync und sync sind hier vor allem für I/O Messungen interessant. Siehe dazu auch Linux I/O Performance Tests mit dd. In diesem Artikel geben wir einige Hintergrundinformationen zu diesen drei Parametern.

dd Dokumentation

dd erlaubt die Angabe folgender Flags:

  • iflag=flag[,flag]...: verwendet die angeführten Flags/Parameter beim Zugriff auf die Eingabedatei (Input File)
  • oflag=flag[,flag]...: verwendet die angeführten Flags/Parameter beim Zugriff auf die Ausgabedatei (Output File)

Hier ist auszugsweise die Beschreibung dieser Flags:[1]

Here are the flags. Not every flag is supported on every operating system.
  • direct: Use direct I/O for data, avoiding the buffer cache. [Anmerkung: gemeint ist hier nicht der Buffer Cache, sondern der Page Cache, siehe Page Cache oder Buffer Cache (Linux Page Cache Grundlagen)] Note that the kernel may impose restrictions on read or write buffer sizes. For example, with an ext4 destination file system and a linux-based kernel, using ‘oflag=direct’ will cause writes to fail with EINVAL if the output buffer size is not a multiple of 512.
  • dsync: Use synchronized I/O for data. For the output file, this forces a physical write of output data on each write. For the input file, this flag can matter when reading from a remote file that has been written to synchronously by some other process. Metadata (e.g., last-access and last-modified time) is not necessarily synchronized.
  • sync: Use synchronized I/O for both data and metadata.

Zugriffsoptionen der open() Funktion

O_DIRECT

O_DIRECT umgeht soweit möglich das I/O Management des Kernels (vor allem den Page Cache), der File I/O geht dabei direkt von/zu den User Space Buffers.

Weitere Informationen zu O_DIRECT liefert die Manpage der open() Funktion:[2]

O_DIRECT (Since Linux 2.4.10)
              Try to minimize cache effects of the I/O to and from this file.  In
              general this will degrade performance, but it is useful in special
              situations, such as when applications do their own caching.  File I/O
              is done directly to/from user space buffers.  The O_DIRECT flag on its
              own makes at an effort to transfer data synchronously, but does not
              give the guarantees of the O_SYNC that data and necessary metadata are
              transferred.  To guarantee synchronous I/O the O_SYNC must be used in
              addition to O_DIRECT.  See NOTES below for further discussion.

O_SYNC, O_DSYNC, O_RSYNC

Der POSIX Standard definiert drei Varianten für synchronized I/O:[3]

  • O_SYNC
  • O_DSYNC
  • O_RSYNC

Die folgende Tabelle zeigt die Unterschiede zwischen O_SYNC, O_DSYNC und O_RSYNC:[4]

O_SYNC O_DSYNC O_RSYNC
Eigenschaft

Der aufrufende Schreib-Prozess wird blockiert bis

  • alle Daten
  • alle Metadaten

auf persistenten Storage geschrieben wurden.

Dies entspricht der Erfüllung der POSIX Definition synchronized I/O file integrity completion.[5]

Der aufrufende Schreib-Prozess wird blockiert bis

  • alle Daten
  • alle Metadaten, die zum späteren Lesen der Daten zwingend erforderlich sind

auf persistenten Storage geschrieben wurden.

Metadaten, die dazu nicht notwendig sind - etwa modification time - müssen hier bei O_DSYNC im Gegensatz zu O_SYNC nicht auf persistenten Storage sein.

Dies entspricht der Erfüllung der POSIX Definition synchronized I/O data integrity completion.[6]

O_RSYNC (nur relevant für Lese-Operationen) muss in Kombination mit O_SYNC oder O_DSYNC verwendet werden.

Der aufrufende Lese-Prozess wird blockiert bis

  • alle Daten und Metadaten (bei Kombination mit O_SYNC)
  • alle Daten und Metadaten, die zum Lesen notwendig sind (bei Kombination mit O_DSYNC)

auf persistenten Storage geschrieben wurden. Dieses Flag ermöglicht einen Kernel das Schreiben von Daten auf persistenten Storage so lange hinauszuzögern, bis die schreibende Applikation die Daten später mit dem O_RSYNC Flag wieder liest.

Linux Kernel bis 2.6.32

Bis einschließlich Kernel Version 2.6.32 implementiert Linux nur O_SYNC. Die glibc verwendet für O_DSYNC und O_RSYNC aber den selben numerischen Wert wie für O_SYNC. Somit scheint es bis Kernel nur O_SYNC Funktionalität zu geben. Tatsächlich bieten Kernel bis Version 2.6.32 aber ausschließlich O_DSYNC Funktionalität. Wenn nämlich O_SYNC genutzt wird, kommt in Wahrheit O_DSYNC Funktionalität vom Kernel:

For now, when the user asks for O_SYNC, we'll actually give O_DSYNC[7]

Linux Kernel ab 2.6.33

Christoph Hellwig hat für den Linux Kernel 2.6.33 die richtige O_SYNC Funktionalität ergänzt.[8] Somit bieten Linux Kernel ab Version 2.6.33 echte O_SYNC und O_DSYNC Funktionalität.

Hier dazu der entsprechende Auszug aus dem Changelog des Kernel 2.6.33:[9]

commit 6b2f3d1f769be5779b479c37800229d9a4809fc3
Author: Christoph Hellwig <hch@lst.de>
Date:   Tue Oct 27 11:05:28 2009 +0100

    vfs: Implement proper O_SYNC semantics
    
    While Linux provided an O_SYNC flag basically since day 1, it took until
    Linux 2.4.0-test12pre2 to actually get it implemented for filesystems,
    since that day we had generic_osync_around with only minor changes and the
    great "For now, when the user asks for O_SYNC, we'll actually give
    O_DSYNC" comment.  This patch intends to actually give us real O_SYNC
    semantics in addition to the O_DSYNC semantics.  After Jan's O_SYNC
    patches which are required before this patch it's actually surprisingly
    simple, we just need to figure out when to set the datasync flag to
    vfs_fsync_range and when not.
    
    This patch renames the existing O_SYNC flag to O_DSYNC while keeping it's
    numerical value to keep binary compatibility, and adds a new real O_SYNC
    flag.  To guarantee backwards compatiblity it is defined as expanding to
    both the O_DSYNC and the new additional binary flag (__O_SYNC) to make
    sure we are backwards-compatible when compiled against the new headers.
    
    This also means that all places that don't care about the differences can
    just check O_DSYNC and get the right behaviour for O_SYNC, too - only
    places that actuall care need to check __O_SYNC in addition.  Drivers and
    network filesystems have been updated in a fail safe way to always do the
    full sync magic if O_DSYNC is set.  The few places setting O_SYNC for
    lower layers are kept that way for now to stay failsafe.
    
    We enforce that O_DSYNC is set when __O_SYNC is set early in the open path
    to make sure we always get these sane options.
    
    Note that parisc really screwed up their headers as they already define a
    O_DSYNC that has always been a no-op.  We try to repair it by using it for
    the new O_DSYNC and redefinining O_SYNC to send both the traditional
    O_SYNC numerical value _and_ the O_DSYNC one.

Einzelnachweise

Weitere Informationen


Foto Werner Fischer.jpg

Autor: Werner Fischer

Werner Fischer arbeitet im Product Management Team von Thomas-Krenn. Er evaluiert dabei neueste Technologien und teilt sein Wissen in Fachartikeln, bei Konferenzen und im Thomas-Krenn Wiki. Bereits 2005 - ein Jahr nach seinem Abschluss des Studiums zu Computer- und Mediensicherheit an der FH Hagenberg - heuerte er beim bayerischen Server-Hersteller an. Als Öffi-Fan nutzt er gerne Bus & Bahn und genießt seinen morgendlichen Spaziergang ins Büro.


Das könnte Sie auch interessieren

Ignoring BGRT: failed to map image header memory
Md5sum und sha1sum zum Überprüfen von Dateidownloads verwenden
Screenshots unter Linux mit Shutter erstellen