Dateienverriegelung
Rachus
- php
0 Beat0 Rachus0 Sven Rautenberg0 Rachus
0 Beat0 Beat
0 Sven Rautenberg
Guten Tag,
leider habe ich in einem anderen Forum, wo ich meine Frage gepostet habe, noch keine Antwort bekommen, daher versuche ich es einmal hier.
Nach langer Suche habe ich in Flatbox eine Funktion gefunden, welche Dateien sperrt. (Zeile 278 im Script) Ich habe mir nun überlegt, diese Funktion zu adaptieren und dabei kam folgender Entwurf heraus (den ich evtl. noch ändere oder erweitere)
class FILELOCK
{
private $filename;
public function __construct($fn)
{
$this->filename=$fh;
for ($i=0; !($fh=@fopen($fn, 'a')) && $i<10; $i++)
{
usleep(100);
}
if (!$fh) return false;
for ($i=0; @flock($fh, LOCK_EX) && $i<10; $i++)
{
usleep(100);
}
fclose($fh);
return true;
}
public function stop()
{
for ($i=0; !($fh=@fopen($this->filename, 'a')) && $i<10; $i++)
{
usleep(100);
}
if (!$fh) return false;
for ($i=0; @flock($fh, LOCK_UN) && $i<10; $i++)
{
usleep(100);
}
fclose($fh);
return true;
}
}
Nun stellen sich mir aber folgende Fragen:
1. Besteht die Sperre noch, wenn ich den Dateizeiger beendet habe (sonst wäre die Funktion ja sinnlos)?
2. Wird am Ende des Scriptes, wenn ich die Sperre nicht entferne, trotzdem die Sperre aufgehoben?
3. Wie finde ich heraus, ob die Sperre tatsächlich gesetzt wurde?
4. An welchem Maßstab mache ich fest, wie lange vor erneutem Öffne-/Sperrversuch gewartet werden soll?
Für Verbesserungsvorschläge und Hilfe jeglicher Art wäre ich sehr dankbar!
for ($i=0; !($fh=@fopen($fn, 'a')) && $i<10; $i++)
{
usleep(100);
}
- Wie finde ich heraus, ob die Sperre tatsächlich gesetzt wurde?
Indem du eben versuchst, eine Sperre zu erhalten.
Ich sehe deshalb nicht, wie dieses Script Race-Conditions aufheben kann.
Ich sehe ein Problem auch bei usleep(100).
sleep wacht auf UNIX bestenfalls alle 1000 us auf. Bei WinXP sogar nur alle 64tel Sekunden. Ist der Wert von usleep unter einem bestimmten Grenzwert, hat das den gleichen Effekt wie usleep(0).
Nun hat usleep den netten Effekt, dass es dem Kernel erlaubt, CPU an den nächsten Prozess zu geben. Das erhöht eher noch die Gefahr von Race-Conditions.
mfg Beat
Indem du eben versuchst, eine Sperre zu erhalten.
Ich sehe deshalb nicht, wie dieses Script Race-Conditions aufheben kann.
Ist dann die Flatboxfunktion nicht verwendbar?
Ich sehe ein Problem auch bei usleep(100).
sleep wacht auf UNIX bestenfalls alle 1000 us auf. Bei WinXP sogar nur alle 64tel Sekunden. Ist der Wert von usleep unter einem bestimmten Grenzwert, hat das den gleichen Effekt wie usleep(0).
Das kann ich ändern. Danke für die Info!
Nun hat usleep den netten Effekt, dass es dem Kernel erlaubt, CPU an den nächsten Prozess zu geben. Das erhöht eher noch die Gefahr von Race-Conditions.
Sollte nicht eigentlich eben die Sperre dafür sorgen, dass kein anderer Prozess auf die Datei zugreift?
Wie realisiere ich denn dann eine Dateisperre, die über eine gewisse Zeit im Script vorhanden bleibt und ich aus der Datei dabei etwas lesen und in sie etwas schreiben kann?
mfg Beat
mfg Rachus
Moin!
Sollte nicht eigentlich eben die Sperre dafür sorgen, dass kein anderer Prozess auf die Datei zugreift?
Wie realisiere ich denn dann eine Dateisperre, die über eine gewisse Zeit im Script vorhanden bleibt und ich aus der Datei dabei etwas lesen und in sie etwas schreiben kann?
Du öffnest die Datei irgendwann, setzt sofort ein Lock (je nach Zugriffsmethoden im Skript), und schließt die Datei nur dann, wenn deine Dateioperation wirklich abgeschlossen ist.
Wenn du in dem Skript nur lesen musst, dann setze ein Shared Lock - dann können parallel weitere Skripte ebenfalls lesen.
Wenn du in dem Skript auch schreiben musst, setze ein Exklusives Lock - das kann nicht parallel mit Shared Locks existieren und garantiert, dass wirklich nur dieses eine Skript in die Datei schreibt.
Aber wie erwähnt: Lies diesen Artikel zum Thema Dateisperren.
- Sven Rautenberg
Danke! Ich hatte zwar den Artikel schon einmal gelesen, aber anscheinend ist es da noch nicht in meinen Kopf gelangt.
Ihr habt mir sehr geholfen! Bei weiteren Problemen/Unklarheiten werde ich auf euch zurückkommen.
Schönen Tag noch!
Rachus
Nun hat usleep den netten Effekt, dass es dem Kernel erlaubt, CPU an den nächsten Prozess zu geben. Das erhöht eher noch die Gefahr von Race-Conditions.
Sollte nicht eigentlich eben die Sperre dafür sorgen, dass kein anderer Prozess auf die Datei zugreift?
Die Race-Condition ist auf jeden Fall gegeben weil ein open() auf ein File und flock() nacheinander und nicht miteinander ausgeführt werden.
Dazwischen kann immer der Kernel einem anderen Process CPU geben, sprich, dummerweise diesen das gleiche versuchen lassen.
Wie realisiere ich denn dann eine Dateisperre, die über eine gewisse Zeit im Script vorhanden bleibt und ich aus der Datei dabei etwas lesen und in sie etwas schreiben kann?
Ich kann dir keine definitive Lösung geben, nur Literatur.
http://aktuell.de.selfhtml.org/artikel/programmiertechnik/
mfg Beat
Ich kann dir keine definitive Lösung geben, nur Literatur.
http://aktuell.de.selfhtml.org/artikel/programmiertechnik/
Sorry
http://aktuell.de.selfhtml.org/artikel/programmiertechnik/dateisperren/
mfg Beat
Moin!
Nun stellen sich mir aber folgende Fragen:
- Besteht die Sperre noch, wenn ich den Dateizeiger beendet habe (sonst wäre die Funktion ja sinnlos)?
Ja, deine Funktion ist sinnlos. Mit fclose() wird die Dateisperre wieder freigegeben.
- Wird am Ende des Scriptes, wenn ich die Sperre nicht entferne, trotzdem die Sperre aufgehoben?
Am Skriptende werden alle offenen Dateien geschlossen, was ebenfalls alle Sperren aufhebt.
- Wie finde ich heraus, ob die Sperre tatsächlich gesetzt wurde?
Wenn flock() ausgeführt wurde, ist die Sperre gesetzt, sofern du blockierendes Locking benutzt. Wenn du LOCK_NB als Option mit einbindest, kehrt flock() immer sofort zurück, liefert aber den Erfolg des Lock-Setzens als boolsches Funktionsergebnis zurück.
- An welchem Maßstab mache ich fest, wie lange vor erneutem Öffne-/Sperrversuch gewartet werden soll?
Beim blockierenden Setzen eines Locks wartet die Funktion so lange, bis das geforderte Lock gesetzt werden konnte. Insofern ist überhaupt kein Warten notwendig.
Da deine Funktion aber alle Locks sofort durch Dateischließen wieder verliert, kriegst du ja sowieso keine vernünftige Funktion hin.
Lies mal den Artikel zum Thema "Dateisperren". Der erklärt die alle Probleme, die dabei so auftreten können, und wie man sie korrekt behebt.
- Sven Rautenberg