2013-03-26 8 views
7

Ich brauche meinen Code (C++, auf Linux), um eine zweite ausführbare Datei aufzurufen, die zuvor eine Ausgabedatei geschrieben hat, die von dem zweiten Programm gelesen wird. Hat der naive Ansatz,Kann eine Datei sofort zum Lesen geöffnet werden, nachdem ofstream :: close() zurückgegeben wurde?

std::ofstream out("myfile.txt"); 
// write output here 
out.close(); 
system("secondprogram myfile.txt"); 

leiden an einer potentiellen Race-Bedingung, wo auch out.close obwohl() ausgeführt hat, kann die Datei nicht sofort von secondprogram gelesen werden? Wenn ja, was ist die beste Vorgehensweise, um dies zu lösen?

Drei Noten:

  • Wenn diese Datei-System-abhängig ist, bin ich im Verhalten auf ext3 und tmpfs interessiert.
  • Offensichtlich gibt es andere Gründe (Dateiberechtigungen usw.), warum das zweite Programm die Datei möglicherweise nicht öffnen kann; Ich bin nur an dem Potenzial für eine Race-Bedingung interessiert.
  • Der hardcoded Dateiname in dem obigen Beispiel dient der Einfachheit; in Wirklichkeit verwende ich mkstemp.
+0

Ja, es ist garantiert. Sind Sie sicher, dass das Problem dabei ist? Hast du dein Programm "strace"? –

+0

@BasileStarynkevitch Ich hatte (noch) kein Problem: Ich wollte nur überprüfen, dass ich keine Zukunft bekommen werde. Können Sie näher ausführen, ob es C++, Linux, das Dateisystem oder etwas anderes ist, das diese Garantie bietet? –

+0

Ich würde sagen, alle von ihnen müssen Teile davon garantieren: Ihre C++ - Implementierung muss garantieren, dass der Puffer geleert wird und 'close()' nur zurückgibt, nachdem der relevante syscall zum 'Schließen' einer Datei zurückgegeben wurde, der Kernel muss garantieren, dass nach dem Zurücksenden des Syscalls die Datei geöffnet werden kann und alle über das alte Handle vorgenommenen Änderungen sichtbar sind und das VFS sicherstellen muss, dass die Caches korrekt verarbeitet werden.Ich stimme @BasileStarynkevitch zu: All dies sollte halten und Sie sollten keine Probleme haben. – us2012

Antwort

1

Es gibt einen möglichen Fehlermodus, den ich früher vermisst habe: Sie scheinen keine Möglichkeit zu haben, sich wiederherzustellen, wenn die Datei nicht von secondprogram geöffnet werden kann. Das Problem ist nicht, dass die Datei gesperrt/inkonsistent sein kann, nachdem close() zurückkehrt, aber dass ein anderes Programm, völlig unabhängig von Ihrem, die Datei zwischen close() und system() (sagen wir, ein AV-Scanner, jemand grep Ing durch das Verzeichnis zu öffnen die Datei, ein Backup-Prozess). Wenn das passiert, wird secondprogram fehlschlagen, obwohl Ihr Programm sich ordnungsgemäß verhält.

TL/DR: Obwohl alles wie erwartet funktioniert, müssen Sie den Fall berücksichtigen, dass secondprogram die Datei möglicherweise nicht öffnen kann!

0

Nach cplusplus.com wird die Funktion zurückgegeben, wenn alle Daten auf die Festplatte geschrieben wurden. Also sollte es keine Rassenbedingung geben.

+1

Ich glaube nicht, dass das stimmt. Was es bedeutet "Jede ausstehende Ausgabesequenz wird in die physische Datei geschrieben." ist wahrscheinlich, dass der interne Puffer des "fstream" geleert wird, so dass alle Änderungen an der Datei für alle anderen sichtbar sind. Ich wäre sehr überrascht, wenn der Standard vorschreibt, dass 'close()' das Betriebssystem zwingt, seine Caches sofort auf die Festplatte zu schreiben. – us2012

+1

Ihr Link zu cplusplus.com sagt nicht streng, dass die Daten zu der Zeit geschrieben werden, die fstream :: close zurückgibt. Es ist fast sicher nicht: siehe http://stackoverflow.com/questions/705454/does-linux-guarantee-the-contents-of-a-file-isflushed-to-disc-after-close –

+0

Dies ist Warum habe ich _nach_ erklärt, ich habe die C++ stdlib nicht implementiert und kann Ihnen das nicht sagen. –

3

Sobald die Datei geschlossen wurde, wird garantiert, dass alle geschriebenen Daten aus den Puffern des Objekts ofstream gelöscht werden (denn an diesem Punkt können Sie es ohne jegliches Risiko des Verlusts von Daten zerstören, und die Datei wird geschlossen intern vom Destruktor bei Bedarf erledigt). Dies bedeutet nicht, dass sich die Daten zu diesem Zeitpunkt physisch auf der Festplatte befinden (wahrscheinlich aufgrund des Caching-Verhaltens der Festplattentreiber des Betriebssystems), aber jedes Programm, das im selben Betriebssystem ausgeführt wird, kann die Datei konsistent lesen (da das Betriebssystem dann das Lesen von den zwischengespeicherten Daten durchführt). Wenn Sie die BS-Puffer auf den Datenträger leeren müssen (der für Ihr Zweitprogramm nicht benötigt wird, um die Eingabedatei korrekt zu lesen), dann sollten Sie sich die sync()-Funktion in <unistd.h> ansehen.