Ich würde gerne wissen, ob Linux-Lese- / Schreibsystemaufrufe nicht synchronisierte Lese- / Schreibvorgänge (nicht anhängende Schreibvorgänge) in nicht überlappenden Regionen einer einzelnen Festplattendatei von mehreren Threads oder Prozessen unterstützen. Jeder Thread sucht in seinem eigenen Bereich der Datei und liest/schreibt ausschließlich aus/in diesen Bereich, ohne sich mit den Bereichen zu überschneiden, in denen andere Threads arbeiten.
POSIX legt in XSH 2.9.7 fest, dass im Wesentlichen alle I/O-Funktionen bezüglich ihrer POSIX-spezifizierten Wirkungen atomar zueinander sind. Eine lange Liste der spezifischen Funktionen, auf die dies zutrifft, ist angegeben, und open()
, lseek()
, read()
, write()
, und close()
sind alle dran. Daher
Wenn zwei Threads jeweils eine dieser Funktionen aufrufen, soll jeder Aufruf entweder alle spezifizierten Effekte des anderen Aufrufs sehen oder keine davon.
Das hängt nicht von irgendeiner externen Synchronisation ab, selbst für Operationen auf Dateideskriptoren, die mit derselben offenen Dateibeschreibung verbunden sind.
Es kann mehrere offene Dateibeschreibungen für dieselbe Datei geben, selbst in einem einzigen Prozess (siehe zum Beispiel die Handbuchseite für open(2)). Angesichts mehrerer Threads, die read()
ausführen und write()
Operationen an nicht überlappenden Bereichen derselben regulären Datei, über Dateideskriptoren, die sich auf verschiedene offene Dateibeschreibungen beziehen , bietet POSIX keine Grundlage, um zu erwarten, dass sich diese Operationen gegenseitig stören, unabhängig von der externen Synchronisation der beteiligten Threads. In der Praxis funktioniert es gut.
Wo Sie in Schwierigkeiten geraten können ist, wenn die beteiligten Threads versuchen, Dateideskriptoren zu verwenden, die auf dieselbe offene Dateibeschreibung verweisen. Diese müssen nicht denselben Dateideskriptorwert haben (also dup()
Das Hinzufügen eines Dateideskriptors hilft hier nicht), noch müssen die Threads zum selben Prozess gehören, damit die Situation auftritt. Jede offene Dateibeschreibung hat eine einzige zugeordnete Dateiposition, wenn also zwei verschiedene Threads versuchen, Aufgaben auszuführen, die jeweils separat erforderlich sind Setzen des Datei-Offsets und Übertragen von Daten in oder aus der Datei, und wenn sie dieselbe offene Dateibeschreibung verwenden, reicht die Atomarität der einzelnen Funktionsaufrufe nicht aus, um sicherzustellen, dass die Lese- und Schreibvorgänge an den beabsichtigten Positionen ausgeführt werden. In diesem Szenario ist eine Synchronisierung erforderlich.
Alternativ, wie @maximegorushkin in Kommentaren und @bk2204 in einer anderen Antwort bemerkte, der pread()
und pwrite()
Funktionen führen Positionierung und Datenübertragung in einem einzigen Aufruf durch. Diese befinden sich auch auf der Liste der atomaren E/A-Funktionen und überwinden die Trennung der Positionierung von der Datenübertragung auf einer Per-Data-Transfer-Basis. Ihre Verwendung erfordert besondere Sorgfalt und Buchhaltung, und es gibt Szenarien, in denen dies nicht angemessen ist, aber es kann dennoch für den jeweiligen Fall praktikabel sein.
Daher , wenn zwei verschiedene Threads ohne Synchronisierung mit derselben Datei arbeiten möchten, besteht der sicherste und allgemeinste Ansatz darin, dass jeder die Datei unabhängig voneinander öffnet. Sie stören sich dann nicht gegenseitig, solange ihre E/A-Operationen auf disjunkte Bereiche der Datei beschränkt sind. Auch das Arbeiten mit überlappenden Bereichen der Datei ist nicht ausgeschlossen, aber das führt zu komplexeren, anwendungsspezifischen Überlegungen.
Ja, das ist möglich. Die pread
und pwrite
Mit Funktionen können Sie an einem bestimmten Offset aus einer Datei lesen und schreiben, ohne den Datei-Offset zu ändern. Sie wurden speziell entwickelt, um das Lesen und Schreiben in Multithread-Programmen zu ermöglichen.
Sie sollten beachten, dass pwrite
gegen POSIX verstößt auf einem Dateideskriptor, der mit O_APPEND
geöffnet wurde schreibt immer an das Ende der Datei.