2012-01-31 65 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()查找代码示例。