Wenn lockf
wird mit einem Offset von 0 verwendet, was sind die Unterschiede zwischen flock
und lockf
bei Verwendung im exklusiven Modus, falls vorhanden?
Ich frage, weil ich Code lese, der bedingt in einer dieser beiden Funktionen basierend auf der Plattform kompiliert wird, und ich mögliche Gründe dafür verstehen möchte.
Der praktische Unterschied zw flock()
und lockf()
liegt in der Semantik (Verhalten in Bezug auf Schließen und Weitergeben), Anwendbarkeit über NFS und andere gemeinsam genutzte Dateisysteme und ob die beratenden Sperren für andere Prozesse sichtbar sind, die verwenden fcntl()
Sperren oder nicht.
Die von Ihnen verwendete Bibliothek verfügt einfach über eine Logik, um die gewünschte Semantik basierend auf der aktuellen Plattform auszuwählen.
Wenn die Semantik (Verhalten gegenüber Deskriptorübergabe, Verzweigung usw.) akzeptabel ist, sollten Sie dies vorziehen lockf()
/fcntl()
sperrt über flock()
Sperren in Linux, einfach weil ersteres auf NFS-Dateisystemen usw. funktioniert, während letzteres dies nicht tut. (Auf BSDs und Mac OS X glaube ich, dass Sie explizit verwenden müssen fcntl()
stattdessen.)
Unter Linux, lockf()
ist nur ein Wrapper herum fcntl()
während flock()
Sperren sind separat (und funktionieren nur auf lokalen Dateisystemen, nicht zB auf NFS-Mounts auf Kerneln vor 2.6.12). Das heißt, ein Prozess kann eine exklusive Beratung haben flock()
eine Datei sperren, während ein anderer Prozess eine exklusive Empfehlung hat fcntl()
sperren Sie dieselbe Datei. Beides sind beratende Sperren, aber sie interagieren nicht.
An Mac OS X und FreeBSD, lockf()
/flock()
/fcntl()
Sperren interagieren alle, obwohl Entwicklern empfohlen wird, nur eine der Schnittstellen in einer Anwendung zu verwenden. Allerdings nur fcntl()
Schlösser funktionieren NFS-Mounts (und natürlich nur, wenn sowohl der NFS-Client als auch der Server so konfiguriert wurden, dass sie Datensatzsperren unterstützen, was überraschend selten in zB Webhosting-Umgebungen vorkommt; eine große Ursache für Kopfschmerzen für einige Web(Framework)-Entwickler).
POSIX gibt nicht explizit an, wie lockf()
/flock()
/fcntl()
Schlösser sollten interagieren, und in der Vergangenheit gab es Unterschiede. Jetzt hat sich die Lage etwas beruhigt, und man kann etwa Sag das
-
fcntl()
Schlösser sind die zuverlässigsten
Über alle Architekturen hinweg haben sie die besten Chancen, direkt an beispielsweise gemeinsam genutzten Dateisystemen zu arbeiten – beispielsweise NFS- und CIFS-Mounts.
-
Meistens, lockf()
wird als “Kurzschrift” für implementiert fcntl()
Die andere Alternative, als “Kurzschrift” für flock()
ist möglich, aber heutzutage selten.
-
fcntl()
und flock()
haben unterschiedliche Semantik bzgl. Vererbung und automatische Freigaben
fcntl()
Sperren bleiben über ein erhalten exec()
aber nicht über a vererbt fork()
. Die Sperren werden freigegeben, wenn der besitzende Prozess schließt irgendein Deskriptor, der auf dieselbe Datei verweist.
Unter Linux, FreeBSD und MAC OS X flock()
Sperren sind mit dem offenen Dateideskriptor gekoppelt: Durch das Übergeben des Deskriptors wird auch die Sperre übergeben. (Die Manpages sagen das “Die Sperre liegt auf der Datei, nicht auf dem Dateideskriptor”. Dies ist kein Widerspruch. Es bedeutet nur, dass das Schloss gilt zur Datei. Es ist immer noch so an den Deskriptor gekoppelt, dass beim Duplizieren des Deskriptors auch dieselbe Sperre übergeben wird.) Daher ist es möglich, dass mehrere Prozesse denselben exklusiven Hinweis haben flock()
gleichzeitig auf dieselbe Datei sperren, wenn sie den Deskriptor vom Urheber nach der erhalten haben flock()
Anruf.
Das Sperren von Dateien ist ein überraschend kompliziertes Problem. Ich persönlich habe die besten Ergebnisse erzielt, indem ich mich einfach daran gehalten habe fcntl()
Verriegelung. Die Semantik bzgl. fcntl()
Sperren sind nicht einfach zu handhaben und können in bestimmten Fällen ehrlich gesagt ärgerlich sein; Es ist nur so, dass ich festgestellt habe, dass es die besten – zuverlässigsten, portabelsten, am wenigsten überraschenden – Ergebnisse liefert.
Der wahrscheinlichste Grund für die bedingte Kompilierung ist, dass keine der beiden Funktionen auf jeder Plattform verfügbar ist.