2012-06-14 3 views
14

Ich arbeite mit einem Multi-Thread-Programm.C wiederherstellen stdout zu Terminal

Zuerst leite ich meine stdout auf eine bestimmte Datei um. Kein Problem dort (ich benutzte dup2(fd, 1) wo fd der Dateideskriptor für die Datei ist).

Danach muss ich meine stdout wieder an das Terminal umleiten.

Mein erster Ansatz:

 /*Declaration*/ 
     fpost_t stream_sdout; 
     /*code*/ 
     if (fgetpos(stdout, &stream_sdout) == -1) 
      perror(Error:); 

Es sagt illegal suchen.
Keine Ahnung, warum das passiert.
Aber wenn ich das zur Arbeit bekomme, dann brauche ich nur fsetpos(stdout, &stream_stdout) und es sollte funktionieren.

Meine zweite Idee war es, die stdout mit dup2(stdout, 4) in die Datei-Deskriptor-Tabelle, an der Position 4 zu kopieren. Aber das funktioniert auch nicht.

Wie kann ich die Standardausgabe auf ihren ursprünglichen Zielort (Terminal, Rohr, Datei, was auch immer) zurückschalten?

+0

Ich habe das Gefühl, dass es so eine schlechte Idee ist, 'stdout' herum zu bewegen - welche Position sollte das _terminal_ in' fgetpos() 'genau angeben? Warum nicht einfach eine Datei öffnen und mit 'fwrite()' oder 'fprintf()' oder 'write()' ausgeben und bei Bedarf über '/ dev/tty' an das Terminal ausgeben? – sarnold

+1

@sarnold: wahrscheinlich, weil das Programm Bibliotheken oder anderen unveränderbaren Code hat, die auf 'stdout' fest verdrahtet sind. – wallyk

+0

@sarnold Ich habe tatsächlich nicht gedacht, dass diese Möglichkeit. Lass mich schnell nachsehen. – Alessandroempire

Antwort

21
#include <unistd.h> 

... 

int saved_stdout; 

... 

/* Save current stdout for use later */ 
saved_stdout = dup(1); 
dup2(my_temporary_stdout_fd, 1); 

... do some work on your new stdout ... 

/* Restore stdout */ 
dup2(saved_stdout, 1); 
close(saved_stdout); 
+2

Haben Sie beim Tippen über meine Schulter gelesen? –

+0

Das hat mir sehr geholfen. Ich frage mich aber, was ist die Funktion von close (saved_stdout)? Ich habe Close zum Schließen von Dateien verwendet, aber ich bin noch nicht vertraut mit der Funktionsweise der gesamten Dup-Funktion. – ThinkBonobo

+1

@ThinkBonobo, 'saved_stdout' ist ein Duplikat (also * dup() *) des ursprünglichen Dateideskriptors für die ursprüngliche Datei, die dem stdout des Programms zugrunde liegt. Wenn es wieder zu (* dup2() *) stdout (Dateideskriptor Nr. 1) dupliziert wird, hat das Programm zwei Kopien/handles/descriptors für die gleiche zugrunde liegende Datei. Dies ist nicht notwendig, sobald die Ausgabeumleitung beendet ist (und Ressourcengrenzen oder Annahmen über Dateisperren usw. durcheinander gebracht werden können). Daher empfiehlt es sich, die Ressource zu löschen, wenn sie nicht mehr benötigt wird. – pilcrow

0

Wenn das Programm in einer Linux-Umgebung ausgeführt wird, können Sie freopen ("/dev/stdout", "a", stdout).

Aber wenn Sie wissen, dass stdout war das Terminal, freopen ("/dev/tty", "a", stdout) oder das Äquivalent für andere Betriebssysteme — sogar Windows.

+1

Wenn 'dup2()' funktioniert, sollte '/ dev/stdout' auf die Datei verweisen. Sie haben also die Ausgabe von der Datei auf die Datei umgestellt, glaube ich. –

+0

@ JonathanLeffler: Wenn er die 'fd's ändert, wäre das wahr. Aus seiner Beschreibung ist nicht ersichtlich, was geschieht. Es scheint, dass er sich stattdessen um die FILE-Verbindungen herum ändert. – wallyk

+0

Da er erwähnt, dass 'dup2()' verwendet wird, um die Standardausgabe zu wechseln, scheint es mir, dass er mit Dateideskriptoren anfängt. Der Code zum Zurücksetzen der Dinge in der Frage ist unheimlich jenseits der Rettung; ein Neuschreiben ist in Ordnung. Aber darum sollen die Antworten natürlich gehen. –

6

Bevor Sie die dup2(fd, STDOUT_FILENO) tun, sollten Sie die aktuelle offene Dateideskriptor für die Standardausgabe speichern, indem Sie int saved_stdout = dup(STDOUT_FILENO); (lassen dup() eine verfügbare Dateideskriptors Nummer für Sie wählen). Nachdem Sie die Ausgabe in eine Datei umgeleitet haben, können Sie dann dup2(saved_stdout, STDOUT_FILENO) ausführen, um die Standardausgabe an die Stelle zurückzuversetzen, an der sie vor dem Start dieses Vorgangs war (und Sie sollten auch saved_stdout schließen).

Sie müssen sich sorgen, um Standard-I/O-Streams (fflush(stdout)) zu geeigneten Zeiten zu spülen, wie Sie damit herumspielen. Das bedeutet "bevor du die Standardausgabe umschaltest".

+3

+1 für STDOUT_FILENO macht es so viel lesbarer. –