2012-06-14 5 views
14

Sto lavorando con un programma multi-thread.C stdout ripristino al terminale

Per prima cosa reindirizzare il mio stdout su un determinato file. Nessun problema lì (ho usato dup2(fd, 1) dove fd è il descrittore di file per il file).

Successivamente, ho bisogno di reindirizzare nuovamente il mio stdout al terminale.

Il mio primo approccio:

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

Dice illegale cercano.
Non ho idea di cosa stia succedendo.
Ma se riesco a farlo funzionare, allora ho solo bisogno di usare fsetpos(stdout, &stream_stdout) e dovrebbe funzionare.

La mia seconda idea, era quella di copiare lo stdout utilizzando dup2(stdout, 4) nella tabella dei descrittori di file, nella posizione 4. Ma anche questo non funziona.

Come posso riportare l'uscita standard alla destinazione originale (terminale, pipe, file, qualsiasi cosa)?

+0

Ho la sensazione che provare a spostare 'stdout' in questo modo è probabilmente una cattiva idea - quale posizione dovrebbe esattamente il rapporto _terminal_ in' fgetpos() '? Perché non aprire semplicemente un file e inviarlo ad esso usando 'fwrite()' o 'fprintf()' o 'write()' e lo output al terminale tramite '/ dev/tty' quando ne hai bisogno? – sarnold

+1

@sarnold: probabilmente perché il programma ha librerie o altro codice inalterabile che sono cablati a 'stdout'. – wallyk

+0

@sarnold in realtà non l'ho pensato a quella posibilità. Fammi controllare velocemente. – Alessandroempire

risposta

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

Mi stavi leggendo da dietro mentre scrivevo? –

+0

Questo mi ha davvero aiutato molto. Mi stavo chiedendo però qual è la funzione di close (saved_stdout)? Ho usato chiudi per chiudere i file ma non ho ancora familiarità con il funzionamento dell'intero processo di duplicazione. – ThinkBonobo

+1

@ThinkBonobo, 'saved_stdout' è un duplicato (quindi, * dup() *) del descrittore di file originale per il file originale sottostante lo stdout del programma. Quando viene nuovamente duplicato su (* dup2() *) stdout (descrittore di file n ° 1), il programma ha due copie/handle/descrittori per lo stesso file sottostante. Non ce n'è bisogno una volta che il reindirizzamento dell'output è terminato (e potrebbe confondere i limiti delle risorse o le ipotesi sui blocchi di file, ecc.), Quindi una buona pratica è quella di eliminare la risorsa quando non è più necessaria. – pilcrow

0

Se il programma viene eseguito su un ambiente Linux, è possibile freopen ("/dev/stdout", "a", stdout).

Ma se si sa che ilè stato il terminale, freopen ("/dev/tty", "a", stdout) o l'equivalente per altri sistemi operativi — anche Windows.

+1

Quando 'dup2()' funziona, '/ dev/stdout' dovrebbe fare riferimento al file. Quindi hai cambiato l'output dal file al file, credo. –

+0

@JonathanLeffler: Se sta cambiando il 'fd's intorno, quello sarebbe vero. È tutt'altro che evidente dalla sua descrizione che è ciò che sta accadendo. Sembra che potrebbe cambiare le connessioni FILE. – wallyk

+0

Poiché menziona l'uso di 'dup2()' per cambiare l'output standard, mi sembra che stia scherzando con i descrittori di file per cominciare. Il codice per ripristinare le cose nella domanda è strano al di là del salvataggio; una riscrittura è in ordine. Ma questo è quello che dovrebbero essere le risposte, naturalmente. –

6

Prima di fare il dup2(fd, STDOUT_FILENO), è necessario salvare la corrente descrittore di file aperto per standard output facendo int saved_stdout = dup(STDOUT_FILENO); (lasciando dup() scegliere un numero descrittore di file disponibili per voi). Quindi, una volta terminato con l'output reindirizzato su un file, è possibile eseguire dup2(saved_stdout, STDOUT_FILENO) per ripristinare l'output standard sul punto in cui si trovava prima di iniziare tutto ciò (e si consiglia di chiudere anche saved_stdout).

È necessario preoccuparsi di svuotare i flussi di I/O standard (fflush(stdout)) nei momenti appropriati mentre si scherza con questo. Ciò significa 'prima di passare lo stdout su'.

+3

+1 per STDOUT_FILENO lo rende molto più leggibile. –

Problemi correlati