2012-01-31 11 views
23

Sto scrivendo una funzione, che, dato un argomento, reindirizzerà lo stdout a un file o leggerà lo stdin da un file. Per fare questo chiudo il descrittore di file associato allo stdout o allo stdin, in modo che quando apro il file si apra sotto il descrittore che ho appena chiuso. Funziona, ma il problema è che una volta fatto questo, ho bisogno di ripristinare lo stdout e lo stdin su cosa dovrebbero essere realmente.Riapertura dei descrittori di file stdin e stdin dopo la loro chiusura

Quello che posso fare per stdout è aperto ("/ dev/tty", O_WRONLY); Ma non sono sicuro del perché funzioni e, cosa più importante, non so di una dichiarazione equivalente per stdin.

così ho, per stdout

close(1); 
if (creat(filePath, O_RDWR) == -1) 
{ 
    exit(1); 
} 

e per stdin

close(0); 
if (open(filePath, O_RDONLY) == -1) 
{ 
    exit(1); 
} 
+2

man 'dup' e' dup2' –

+0

'O_RDWR' è per il parametro' open' 'flags' non per' creat' 'mode'. –

risposta

34

È necessario utilizzare dup() e dup2() per clonare un descrittore di file.

int stdin_copy = dup(0); 
int stdout_copy = dup(1); 
close(0); 
close(1); 

int file1 = open(...); 
int file2 = open(...); 

< do your work. file1 and file2 must be 0 and 1, because open always returns lowest unused fd > 

close(file1); 
close(file2); 
dup2(stdin_copy, 0); 
dup2(stdout_copy, 1); 
close(stdin_copy); 
close(stdout_copy); 

Tuttavia, c'è un dettaglio che si potrebbe desiderare di essere attenti con (da uomo DUP):

I due descrittori non condividono le bandiere descrittore di file (il close-on-execflag) . Il flag close-on-exec (FD_CLOEXEC; vedere fcntl (2)) per il descrittore duplicato è disattivato.

Se si tratta di un problema, potrebbe essere necessario ripristinare il contrassegno close-on-exec, eventualmente utilizzando dup3() anziché dup2() per evitare condizioni di competizione.

Inoltre, tenere presente che se il programma è multithread, altri thread potrebbero accidentalmente scrivere/leggere sul rimappato stdin/stdout.

+0

Grazie, mi ha davvero aiutato! –

+2

Ci sono altri problemi se sei multi-thread - se un altro thread apre un file tra il tuo 'close (0)' (o 'close (1)') e il corrispondente 'open (...)', quindi il suo file diventerà stdin (o stdout). È molto meglio usare 'dup2()' (o 'dup3') per forzare il descrittore di file a essere 0 (o 1), piuttosto che fare affidamento sul comportamento" inutilizzato più basso ". – psmears

14

penso che si può "salvare" i descrittori prima di reindirizzare:

int save_in, save_out; 

save_in = dup(STDIN_FILENO); 
save_out = dup(STDOUT_FILENO); 

tardi puoi utilizzare dup2 per ripristinarli:

/* Time passes, STDIN_FILENO isn't what it used to be. */ 
dup2(save_in, STDIN_FILENO); 

non sto facendo alcun controllo degli errori in questo esempio - si dovrebbe.

0

È possibile creare un processo figlio e impostare il reindirizzamento solo all'interno del figlio. Quindi attendi che il bambino termini e continua a lavorare nel processo genitore. In questo modo non devi preoccuparti di invertire il tuo reindirizzamento.

Basta cercare esempi di codice utilizzando fork() e wait().