2010-03-22 16 views

Antwort

3

Technisch ist fwrite() ein blockierender Aufruf, der erst nach Abschluss der Prozedur zurückkehrt. Die Definition der Vervollständigung für fwrite() bedeutet jedoch, dass die von Ihnen bereitgestellten Daten in einen internen Dateipuffer geschrieben wurden. Als Nebeneffekt kann ein Teil dieses Puffers auch als Teil des Aufrufs fwrite() auf die Festplatte geschrieben werden, aber Sie können sich nicht auf dieses Verhalten verlassen. Wenn Sie unbedingt die Daten auf der Festplatte benötigen, müssen Sie fflush() aufrufen.

+0

Wenn das stimmt, dann tut es genau das, was ich brauche. Durch non-blocking meinte ich nur, dass es beim Schreiben auf Platte nicht blockieren sollte. Ich muss nur einen riesigen Puffer setzen –

+1

Beachten Sie, dass fflush nur garantiert, dass die Daten vom Userland in den Kernel verschoben werden. Der Kernel puffert auch, wenn Sie die Stromversorgung verlieren, können Sie die Daten trotzdem verlieren. Wenn Sie wirklich die Daten auf der Festplatte wollen, müssten Sie eine 'fsync (fileno (fp));; –

+0

Nun, wie ich bereits sagte, ein Nebeneffekt des Aufrufs von fwrite() ist, dass es seinen internen Puffer zu löschen Scheibe. Diese Unbestimmtheit verursacht einen erheblichen Jitter in der Zeitdauer, die Aufrufe von fwrite() dauern. Wie Thomas Pornin sagte, können Sie die Puffergröße einstellen, aber Details darüber, wann fwrite() den Puffer auf die Festplatte löscht, sind implementierungsabhängig. Wenn Sie wirklich ein deterministisches nicht-blockierendes fwrite() - Äquivalent wünschen, müssen Sie entweder diese Verarbeitung auf einen separaten Thread verschieben oder Ihre Daten in den Zwischenspeicherbereich des Speichers schreiben und dann am Ende fwrite() aufrufen. –

2

fwrite() blockiert. fwrite() kann fflush() intern jederzeit aufrufen.

Wenn alles, was Sie brauchen, um zu puffern, dann puffern Sie in Ihrem eigenen Array. Der Puffer von fwrite ist typischerweise ein paar K.

+0

Jede Möglichkeit, um zu erzwingen, dass fwrite intern nicht fflush() wird? Denn das ist was ich brauche .. ich rufe nur "schreiben" und es legt es in einen Puffer und kehrt sofort und vielleicht beginnt es zu schreiben vielleicht nicht, aber es hält nicht mein Programm bis ich flush aufrufen –

7

fwrite()kann blockieren. Es verwendet (normalerweise) einen internen Puffer mit einer maximalen Länge. Er sendet die Daten (ganz oder teilweise in seinem internen Puffer), wenn der Puffer voll ist.

Mit den Funktionen setbuf() und setvbuf() können Sie die maximale Pufferlänge ändern und den Block tatsächlich für den Puffer bereitstellen. Die Details sind jedoch implementierungsabhängig. Daher müssen Sie die Dokumentation für Ihre spezifische C-Bibliothek lesen.

Konzeptionell, wenn Sie unter allen Bedingungen garantiert non-blocking schreibt, dann benötigen Sie potenziell unendliche Puffer, die etwas teuer sein können. Sie könnten Ihre eigenen Funktionen für die Pufferung von Daten (innerhalb eines RAM-Blocks, mit realloc(), um es wachsen zu lassen, wenn nötig) und Schreiben (mit fwrite() und möglich fflush()) nur am Ende machen. Alternativ könnten Sie versuchen, blockierungsfreie E/A zu verwenden, bei denen Schreibfunktionen niemals blockieren, sondern möglicherweise darauf reagieren, dass sie aufgrund interner Überlastungen die Annahme Ihrer Daten verweigern. Nicht blockierende E/A ist nicht Teil des C-Standards selbst (dafür gibt es keine f*()-Funktion), kann aber unter verschiedenen Namen auf einigen Systemen gefunden werden (z. B. mit fcntl() und write() auf Unix-Systemen).

+0

Es ist auch wichtig zu beachten Selbst wenn fwrite blockiert wird, werden nur die Daten an die Kernel/Dateisystem-Ebene übergeben. Der Kernel führt normalerweise eine Pufferung durch, anstatt die Daten sofort auf der Festplatte zu synchronisieren. –

Verwandte Themen