2012-03-24 21 views
0

Also schreibe ich ein Programm, das für immer laufen soll (Client-Server Zeug) in C, und ich schreibe in ein Protokoll. Ich verwende und fprintf, um in die Datei schreiben zu können. Mein Problem ist, dass, da das Programm für immer laufen soll, es wirklich keinen Punkt gibt, wo ich eine fclose setzen kann. Und wenn ich Ctrl + C um den Prozess zu stoppen, und die Protokolldatei zeigt es nichts? Ich möchte fprintf verwenden, weil es mir erlaubt, formatierte Zeichenfolgen zu haben, gibt es eine Möglichkeit für mich, meine Ausgabe zu protokollieren, während ich noch formatierte Zeichenfolgen habe?lesen fprintf, während das Programm läuft

Antwort

4

Was passiert ist, ist, dass die Ausgabe gepuffert wird und wenn das Programm beendet wird, wird der Puffer nie auf Platte gelöscht. Sie können den Puffer entweder regelmäßig leeren (fflush) oder versuchen, das Kill-Signal zu erfassen. Insbesondere sendet Control + C das Signal SIGINT, so dass Sie einen Handler dafür registrieren müssen.

Um möglichen Pufferverlust zu minimieren, würde ich wahrscheinlich beide Strategien verwenden.

How can I catch a ctrl-c event? (C++)

Edit: Wie Adam sagte, können Sie auch einfach öffnen und schließen Sie die Datei dann notwendig, wenn, aber je nachdem, wie häufig Sie schreiben, können Sie in diesem Fall meine Antwort die Datei offen halten würde gelten.

+0

Ich schreibe ziemlich häufig, weshalb ich nicht mit der Methode "Öffnen und Schließen jedes Mal" gehen wollte, danke, dass sie mir gesagt haben, was eigentlich los ist. Ich werde beide Methoden versuchen – user1289479

+1

Wenn Sie nur regelmäßige Spülen, dann können Sie möglicherweise Daten verlieren, ist das Programm vor dem nächsten Flush. Wenn Sie versuchen, Signale zu erfassen, können Sie das besser verhindern, und deshalb ist beides ideal. Wenn Sie nicht besonders an der IO-Leistung interessiert sind, können Sie nach jedem Schreibvorgang einfach fflush. Abhängig davon, wie aggressiv der Kernel und der physische Plattencache sind, kann fflush nach jedem Schreibvorgang tatsächlich eine sehr geringe Auswirkung auf die Leistung haben. – Corbin

1

Jedes Mal, wenn Sie eine Protokollnachricht schreiben möchten, öffnen Sie die Datei im Anfügemodus, drucken Sie Ihren Text am Ende der Datei und schließen Sie ihn dann.

1

setbuf(), setvbuf(), oder fflush(), - und trap SIGINT oder was immer in Bezug auf Ihr System angemessen ist.


D.h.

#include <stdio.h> 
#include <unistd.h> /* for sleep() in this example */ 

int main(void) 
{ 
    FILE *fh; 
    char *fn = "main.log"; 
    int i; 

    if ((fh = fopen(fn, "w")) == NULL) { 
     fprintf(stderr, 
      "Unable to open file %s\n", fn); 
     return 1; 
    } 

    setbuf(fh, NULL); /* Turns buffering completely off */ 

    for (i = 1; ; ++i) { 
     fprintf(fh, "%d ok ", i); 
     if (!(i%120)) 
      fprintf(fh, "\n"); 
     sleep(1); 
    } 

    fclose(fh); 

    return 0; 
} 

in anderer Konsole:

$ tail -f MAIN.LOG

Ausbeute: 1 OK 2 OK 3 OK 4 OK 5 OK 6 OK^C

Or fflush(fh) wenn Sie Schreibpuffer spülen möchten.

stdio.h:>


int setvbuf(FILE* stream, char* buf, int mode, size_t size);
        Kontrollen Pufferung für Stream-Stream. Modus ist _IOFBF für vollständige Pufferung, _IOLBF für Zeilenpufferung, _IONBF für keine Pufferung. Nicht-Null-Puffer spezifiziert einen Puffer der zu verwendenden Größengröße; Andernfalls wird ein Puffer zugewiesen. Gibt bei einem Fehler einen Wert ungleich Null zurück. Der Anruf muss vor jedem anderen Vorgang im Stream erfolgen.


void setbuf(FILE* stream, char* buf);
        Pufferung Steuerungen für Stream-Stream. Für null buf schaltet Pufferung aus, ansonsten entspricht (void) setvbuf (stream, buf, _IOFBF, BUFSIZ).


int fflush(FILE* stream);
        Flushes Stream Stream und gibt Null auf Erfolg oder EOF im Fehlerfall. Effekt undefiniert für den Eingabestream. fflush (NULL) löscht alle Ausgabeströme.

+0

+1 Sehr gründliche Antwort! – Corbin

0

Ich würde mit Corbins Antwort gehen, aber Sie fragte, ob es eine andere Möglichkeit gibt, formatierte Ausgabe zu bekommen.

Es gibt: Sie könnten sprintf() in einen Zeichenpuffer verwenden und dann unbuffered open/write/close I/O verwenden.

Aber tun Sie das nicht. Benutze weiterhin fopen() und co. Und fange das SIGINT.