Können mehrere Prozesse mit fopen ohne Parallelitätsprobleme an eine Datei angehängt werden?

Lesezeit: 6 Minuten

Benutzer-Avatar
Gelöscht

Ich habe einen Prozess, der eine Datei im Anhängemodus öffnet. In diesem Fall handelt es sich um eine Protokolldatei. Beispielcode:

int main(int argc, char **argv) {
    FILE *f;
    f = fopen("log.txt", "a");
    fprintf(f, "log entry line");
    fclose(f);
}

Zwei Fragen:

  1. Wenn ich mehrere Prozesse habe, die an dieselbe Datei angehängt sind, wird jede Protokollzeile deutlich angezeigt oder können sie verschachtelt werden, wenn der Kontext des Prozesses wechselt?
  2. Wird dieser Schreibblock blockiert, wenn viele Prozesse Zugriff auf die Datei benötigen und daher Parallelitätsprobleme verursachen?

Ich erwäge, dies entweder in seiner einfachsten Form zu tun oder Zeromq zu verwenden, um Protokolleinträge über Pipes zu einem Protokollsammler zu pumpen.

Ich habe Syslog in Betracht gezogen, möchte aber keine Plattformabhängigkeiten von der Software.

Die Standardplattform ist übrigens Linux.

Ich weiß es nicht fopen und fprintf aber du könntest open die Datei mit O_APPEND. Dann jeweils write geht problemlos ans Ende der Datei (ohne sich mit einem anderen Schreibvorgang zu vermischen).

Suchen Sie eigentlich in der Standard:

Der dem geöffneten Stream zugeordnete Dateideskriptor soll zugewiesen und geöffnet werden, als ob durch einen Aufruf von open() mit den folgenden Flags:

a or ab          O_WRONLY|O_CREAT|O_APPEND

Also denke ich, dass es sicher ist fprintf aus mehreren Prozessen, solange die Datei mit geöffnet wurde a.

  • Sie müssen noch die Pufferung auf no oder line schalten. Bei voller Pufferung kann es sein, dass mitten im Eintrag der Puffer ausgeht und damit Write aufgerufen wird.

    – Jan Hudec

    26. September 2011 um 9:11 Uhr

  • @ Jan Hudec Das stimmt. Ein weiterer Grund für die Verwendung write(2) direkt.

    – Cnicutar

    26. September 2011 um 9:14 Uhr

Benutzer-Avatar
glglgl

Das Standard (für open/write, nicht fopen/fwrite) besagt das

Wenn das O_APPEND-Flag der Dateistatus-Flags gesetzt ist, soll der Datei-Offset vor jedem Schreibvorgang auf das Ende der Datei gesetzt werden, und zwischen dem Ändern des Datei-Offsets und dem Schreibvorgang soll keine dazwischenliegende Dateimodifikationsoperation erfolgen.

Zum fprintf() verwendet werden, müssen Sie die Pufferung für die Datei deaktivieren.

  • Wichtig: Das ist für open/write, nicht fopen/fwrite.

    – Jan Hudec

    26. September 2011 um 8:44 Uhr

  • Richtig, aber write() “liegt unter” fwrite() und fprintf(), dh von ihnen verwendet wird. Ist die Pufferung deaktiviert, wird sie sogar 1:1 verwendet. (Aber sagen Sie das besser explizit, also haben Sie Recht.)

    – glglgl

    26. September 2011 um 8:45 Uhr


  • Es ist nicht erforderlich, die Pufferung zu deaktivieren, damit dies funktioniert. Tatsächlich hilft die Zeilenpufferung sicherzustellen, dass ganze Zeilen gleichzeitig geschrieben werden

    – Per Johansson

    26. September 2011 um 8:50 Uhr

  • @glglgl: Ja, write “liegt unter” fwriteaber nichts legt das fest fwrite übergibt die Daten an write an einem Stück. In der Praxis ist dies der Fall, wenn die Pufferung ganz ausgeschaltet ist oder die Zeilenpufferung eingeschaltet ist und die Zeile die Puffergröße nicht überschreitet.

    – Jan Hudec

    26. September 2011 um 9:10 Uhr

  • Obwohl das Schreiben die Atomarität sicherstellt, hängt die Schreibreihenfolge von zwei Prozessen vom Betriebssystem ab. Selbst wenn also Prozess1 write() vor write() von Prozess2 aufruft, hängt die Reihenfolge der geschriebenen Daten vom Betriebssystem ab. Um die Reihenfolge zu garantieren, ist es daher am besten, Mutex zu verwenden.

    – Rechnung

    22. Dezember 2012 um 19:20 Uhr


Sie werden sicherlich Plattformabhängigkeiten haben, da Windows nicht mehrere Prozesse verarbeiten kann, die an dieselbe Datei angehängt werden.

In Bezug auf Synchronisationsprobleme denke ich, dass Ihnen die zeilengepufferte Ausgabe die meiste Zeit ersparen /sollte/, dh mehr als 99,99% der kurzen Protokollzeilen sollten laut meinem kurzen Shell-basierten Test intakt sein, aber nicht jedes Mal. Explizite Semantik ist definitiv vorzuziehen, und da Sie diesen Hack sowieso nicht systemunabhängig schreiben können, würde ich einen Syslog-Ansatz empfehlen.

  • Danke – das wollte ich nur wissen. Das mehrfache Anhängen von Windows war etwas, worüber ich mir Sorgen machte.

    – Gelöscht

    26. September 2011 um 9:07 Uhr

Wenn Ihre Prozesse so etwas schreiben werden:

"Here's process #1"
"Here's process #2"

Sie werden wahrscheinlich so etwas bekommen wie:

"Hehere's process #2re's process #1"

Sie müssen sie synchronisieren.

Benutzer-Avatar
Peter Wilson

BEARBEITEN um deine Fragen explizit zu beantworten:

  1. Wenn ich mehrere Prozesse habe, die an dieselbe Datei angehängt sind, wird jede Protokollzeile deutlich angezeigt oder können sie verschachtelt werden, wenn der Kontext des Prozesses wechselt?

Ja, jede Protokollzeile wird intakt angezeigt, da gemäß msdn/vs2010:

Diese Funktion [that is, fwrite( )] sperrt den aufrufenden Thread und ist somit Thread-sicher. Eine Version ohne Sperre finden Sie unter _fwrite_nolock.

Dasselbe wird angedeutet die GNU-Manpage:

“— Funktion: size_t fwrite (const void *data, size_t size, size_t count, FILE *stream)

This function writes up to count objects of size size from the array data, to the stream stream. The return value is normally count, if the call succeeds. Any other value indicates some sort of error, such as running out of space. 

— Funktion: size_t fwrite_unlocked (const void *data, size_t size, size_t count, FILE *stream)

The fwrite_unlocked function is equivalent to the fwrite function except that it does not implicitly lock the stream.

This function [i.e., fwrite_unlocked( )] is a GNU extension. "
  1. Wird dieser Schreibblock blockiert, wenn viele Prozesse Zugriff auf die Datei benötigen und daher Parallelitätsprobleme verursachen?

Ja, implizit aus Frage 1.

  • Danke für die Antwort. Das potenzielle Problem, das ich habe, ist Parallelität, sodass das Sperren Probleme damit verursacht. Ich habe positiv abgestimmt, da der Anwendungsfall immer noch gültig und beschreibend ist. Danke noch einmal!

    – Gelöscht

    26. September 2011 um 9:57 Uhr

  • Oh, endlich verstehe ich es. Bei “Parallelitätsproblem” befürchten Sie, dass Prozess2 blockiert, während Prozess1 versucht, in die Protokolldatei zu schreiben. Ich habe meine Antwort bearbeitet, um beide Fragen explizit anzusprechen.

    – Peter Wilson

    26. September 2011 um 10:30 Uhr

  • Das ist es 🙂 – trotzdem nochmals vielen Dank für deine Antwort. Ich würde dies bei geringen Gleichzeitigkeitsanforderungen verwenden.

    – Gelöscht

    26. September 2011 um 10:34 Uhr

Benutzer-Avatar
Harald

Wenn Sie keine Synchronisierung durchführen, können sich die Protokollzeilen überschneiden. Um Nummer zwei zu beantworten, hängt dies davon ab, wie Sie den Sperr- und Protokollierungscode implementieren. Wenn Sie nur sperren, in die Datei schreiben und entsperren, kann dies zu Problemen führen, wenn viele Prozesse gleichzeitig versuchen, auf die Datei zuzugreifen.

  • Danke für die Antwort. Das potenzielle Problem, das ich habe, ist Parallelität, sodass das Sperren Probleme damit verursacht. Ich habe positiv abgestimmt, da der Anwendungsfall immer noch gültig und beschreibend ist. Danke noch einmal!

    – Gelöscht

    26. September 2011 um 9:57 Uhr

  • Oh, endlich verstehe ich es. Bei “Parallelitätsproblem” befürchten Sie, dass Prozess2 blockiert, während Prozess1 versucht, in die Protokolldatei zu schreiben. Ich habe meine Antwort bearbeitet, um beide Fragen explizit anzusprechen.

    – Peter Wilson

    26. September 2011 um 10:30 Uhr

  • Das ist es 🙂 – trotzdem nochmals vielen Dank für deine Antwort. Ich würde dies bei geringen Gleichzeitigkeitsanforderungen verwenden.

    – Gelöscht

    26. September 2011 um 10:34 Uhr

1072460cookie-checkKönnen mehrere Prozesse mit fopen ohne Parallelitätsprobleme an eine Datei angehängt werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy