2012-01-31 68 views
23

我正在寫一個函數,它給出參數將重定向標準輸出到文件或從文件讀取標準輸入。爲此,我關閉與stdout或stdin關聯的文件描述符,這樣當我打開文件時,它會在我剛剛關閉的描述符下打開。這有效,但問題是,一旦完成,我需要恢復stdout和stdin到他們真正應該做的。關閉它們後重新打開標準輸出和標準輸入文件描述符

我可以爲標準輸出做什麼打開(「/ dev/tty」,O_WRONLY);但我不確定爲什麼這會起作用,更重要的是我不知道stdin的等價語句。

所以我有,標準輸出

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

和標準輸入

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

man'dup'和'dup2' – 2012-01-31 17:35:26

+0

'O_RDWR'用於'open'' flags'參數,不適用於'creat'' mode'參數。 – 2016-03-21 12:22:48

回答

34

您應該使用dup()和dup2()來克隆文件描述符。

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); 

然而,有你可能要小心(從人DUP)一個小細節:

兩個描述符不共享文件描述符標誌(在 近距離上execflag) 。重複描述符的關閉執行標誌(FD_CLOEXEC;請參閱fcntl(2)) 已關閉。

如果這是一個問題,您可能必須恢復執行close-on標誌,可能使用dup3()而不是dup2()來避免競爭條件。

此外,請注意,如果您的程序是多線程的,其他線程可能會意外地寫入/讀取到重新映射的stdin/stdout。

+0

謝謝,這真的幫助我了! – 2012-08-02 10:18:47

+2

如果你是多線程的,還有其他問題 - 如果另一個線程在你的close(0)(或close(1))和相應的open(...)之間打開一個文件,那麼它的文件將成爲stdin(或stdout)。使用'dup2()'(或'dup3')強制文件描述符爲0(或1),而不是依賴「最低未使用」行爲會更好。 – psmears 2015-09-06 22:26:51

14

我覺得你可以 「拯救」 的描述重定向前:

int save_in, save_out; 

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

後來您可以使用dup2來恢復它們:

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

我沒有做任何的錯誤在這個例子檢查 - 你應該。

0

您可以創建子進程,並僅在子進程內設置重定向。然後等待孩子終止,並繼續在父進程中工作。這樣你根本不必擔心逆轉你的重定向。

只需使用fork()和wait()查找代碼示例。