2012-06-14 28 views
14

Pracuję z programem wielowątkowym.C przywróć stdout do terminala

Najpierw przekierowuję moje wyjście do określonego pliku. Nie ma problemu (użyłem dup2(fd, 1) gdzie fd jest deskryptorem pliku dla pliku).

Następnie muszę ponownie przekierować moje wyjście do terminalu.

Moje pierwsze podejście:

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

Mówi nielegalne poszukiwania.
Nie mam pojęcia, dlaczego tak się dzieje.
Ale jeśli sprawię, że to zadziała, to będę musiał tylko użyć fsetpos(stdout, &stream_stdout) i powinno działać.

Moim drugim pomysłem było skopiowanie standardowego stdouta przy użyciu dup2(stdout, 4) do tabeli deskryptorów plików na pozycji 4. Ale to też nie działa.

Jak przełączyć standardowe wyjście z powrotem do pierwotnego miejsca docelowego (terminal, potok, plik, cokolwiek)?

+0

Mam przeczucie, że próba przeniesienia 'stdout' dookoła w ten sposób jest prawdopodobnie złym pomysłem - jaką dokładnie pozycję powinien mieć _terminalny_ raport w' fgetpos() '? Dlaczego po prostu nie otwierać pliku i wyświetlać go przy użyciu 'fwrite()' lub 'fprintf()' lub 'write()' i wyprowadzać do terminala za pomocą '/ dev/tty' kiedy jest to potrzebne? – sarnold

+1

@sarnold: prawdopodobnie dlatego, że program ma biblioteki lub inny niezmienny kod, który jest podłączony do 'stdout'. – wallyk

+0

@sarnold i faktycznie nie dałam mu tego do myślenia. Pozwól mi szybko sprawdzić. – Alessandroempire

Odpowiedz

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

Czy czytałeś przez ramię podczas pisania? –

+0

To bardzo mi pomogło. Zastanawiam się jednak, jaka jest funkcja close (saved_stdout)? Użyłem blisko do zamykania plików, ale nie jestem jeszcze zaznajomiony z działaniem całego procesu dup. – ThinkBonobo

+1

@ThinkBonobo, 'saved_stdout' jest duplikatem (stąd, * dup() *) oryginalnego deskryptora pliku dla oryginalnego pliku leżącego u podstaw stdout programu. Kiedy jest on ponownie powielany z powrotem do (* dup2() *) stdout (deskryptor pliku nr 1), program ma dwie kopie/uchwyty/deskryptory dla tego samego bazowego pliku. Nie ma takiej potrzeby, gdy przekierowanie wyjścia zostanie zakończone (i może wprowadzić w błąd ograniczenia zasobów lub założenia dotyczące blokad plików itp.), Więc dobrą praktyką jest odrzucanie zasobu, gdy nie jest już potrzebny. – pilcrow

0

Jeśli program działa w środowisku Linux, można freopen ("/dev/stdout", "a", stdout).

Ale jeśli wiesz, że stdout był terminalem, freopen ("/dev/tty", "a", stdout) lub odpowiednikiem innych systemów operacyjnych — nawet Windows.

+1

Kiedy 'dup2()' działa, '/ dev/stdout' powinien odnosić się do pliku. Tak więc, jak sądzę, przełączono dane wyjściowe z pliku do pliku. –

+0

@ JonathanLeffler: Jeśli zmienia on "fd", to byłoby prawdą. Daleko nie wynika z jego opisu, co się dzieje. Wygląda na to, że zamiast tego może zmieniać połączenie PLIKU. – wallyk

+0

Ponieważ wspomina używanie 'dup2()' do przełączania standardowego wyjścia, wydaje mi się, że na początku ma kłopot z deskryptorami plików. Kod do resetowania rzeczy w pytaniu jest dziwny nie do ratowania; przepisanie jest w porządku. Ale o to właśnie powinny odpowiedzieć oczywiście. –

6

Przed zrobić dup2(fd, STDOUT_FILENO), należy zapisać bieżący otwarty deskryptor pliku dla standardowego wyjścia wykonując int saved_stdout = dup(STDOUT_FILENO); (pozwalając dup() wybrać dostępny numer deskryptora pliku dla Ciebie). Następnie, po zakończeniu przetwarzania wyjścia przekierowanego do pliku, można wykonać dup2(saved_stdout, STDOUT_FILENO), aby przywrócić standardowe wyjście do miejsca, w którym znajdował się przed rozpoczęciem tego wszystkiego (i należy zamknąć także saved_stdout).

Musisz się martwić o przepłukiwanie standardowych strumieni we/wy (fflush(stdout)) w odpowiednich momentach, gdy będziesz się z tym bałaganić. Oznacza to "zanim przełączysz się na stdout".

+3

+1 dla STDOUT_FILENO sprawia, że ​​Sooo jest o wiele bardziej czytelny. –

Powiązane problemy