![]() |
Sperren von Dateien: Gleichzeitige Zugriffe auf Dateien |
Dieser Artikel behandelt das Sperren von Dateien in PHP, Perl, Python und Java. Es werden zum einen die Grundlagen veranschaulicht und zum anderen konkrete Codebeispiele geliefert, mit deren Hilfe es möglich ist, Dateien auf korrekte Weise zu sperren.
In Webanwendungen kommt es häufiger vor, dass auf Dateien zugegriffen werden muss - sowohl lesend als auch schreibend. Hierbei treten allerdings Probleme auf: Wenn mehrere Prozesse gleichzeitig auf die Datei zugreifen, kann es zu Konflikten kommen, und in ungünstigen Fällen kann der Inhalt der Datei durcheinandergebracht oder gar komplett gelöscht werden. Natürlich finden Zugriffe auf die gleiche Datei nie exakt gleichzeitig statt (selbst auf Mehrprozessorsystemen nicht), aber wenn bestimmte Aktionen nicht atomar ablaufen, das heißt, wenn sie unterbrochen werden können und zwischenzeitlich eine andere Aktion bevorzugt wird, dann kommt es zu eben diesen Problemen. Folgendes Beispiel soll dies verdeutlichen:
Gegeben sei ein einfaches Script, das eine Datei öffnet, eine Zahl, die in dieser Datei gespeichert ist, ausliest, den Dateiinhalt löscht und dann die Zahl um eins erhöht wieder hineinschreibt (also ein einfacher Zähler). Bricht man diese Aktionen in ihre Bestandteile herunter, für die heutige Betriebssysteme garantieren können, dass sie atomar ablaufen, d.h. nicht unterbrochen werden können, dann werden folgende Schritte durchgeführt:
Folgendes Szenario zeigt, wie bereits dieses einfache Script zum Stolpern gebracht werden kann. Vorraussetzung ist, dass zwei Besucher das Script fast zeitgleich aufrufen. Die Aktionen (da sie die gleiche Datei betreffen) werden zwar nie exakt zeitgleich ausgeführt, aber die Reihenfolge ist absolut zufällig. Im folgenden soll gezeigt werden, was im ungünstigsten Fall passieren kann (die beiden Scriptaufrufe sind jeweils andersfarbig hervorgehoben), der Zähler sei am Anfang z.B. 42:
42 ist0 an43 in die Datei1 in die DateiWie dieses Beispiel zeigt, kann das fast gleichzeitige Ausführen von Scripten zu Probleme führen, die man auf einem Client-System in der Regel nicht gewohnt ist. Man nennt diese Probleme auch race conditions. Der Ausweg aus dieser Situation (im Dateifall) ist das Sperren von Dateien, auf Englisch file locking genannt. Damit kann verhindert werden, dass die Dateien von mehr als einem Programm gleichzeitig verwendet werden.
Es gibt zwei Arten von Dateisperren:
Unterschiedliche Betriebssysteme implementieren Sperren unterschiedlich. Microsoft Windows implementiert ausschließlich verpflichtende Sperren. UNIX-artige Betriebssysteme wie Linux, FreeBSD oder Mac OS X implementieren hauptsächlich freiwillige Sperren, während verpflichtende Sperren zumindest unter Linux wahlweise unterstützt werden, sofern sie über ein vergleichsweise aufwändiges Verfahren dateisystem- und dateiweise aktiviert werden. Im Folgenden wird davon ausgegangen, dass immer nur kooperative Sperren verwendet werden, denn wenn jedes Programm, das auf die Datei zugreifen will, die Dateisperrfunktionalität nutzt, gibt es keine effektiven Unterschiede zwischen kooperativen und verpflichtenden Sperren - bei verpflichtenden Sperren werden zusätzlich jedoch Dateizugriffe von anderen Programmen untersagt, die diese Funktionalität nicht nutzen.
Ferner gibt es zwei verschiedene Stufen, eine Datei zu sperren:
Wenn ein Programm den Inhalt einer Datei lediglich auslesen will, dann ist eine mitbenutzbare Sperre das Mittel der Wahl. Denn für die Dauer des Lesevorgangs dürfen andere Programme die Datei natürlich weiterhin auslesen, der Schreibzugriff (bei dem eine exklusive Sperre verwendet würde) muss jedoch bis zum Ende des Lesevorgangs warten. Wenn ein Programm auf die Datei selbst schreiben will, dann ist eine exklusive Sperre das Mittel der Wahl, denn dann müssen alle anderen Zugriffe bis zum Ende des Schreibvorgangs warten.