【问题标题】:How to recover stdin overwritten by dup2?如何恢复被 dup2 覆盖的标准输入?
【发布时间】:2019-05-24 06:54:48
【问题描述】:

我正在尝试用另一个管道替换标准输入,然后将原始标准输入放回 fd #0。

例如

dup2(p, 0); // p is a pre-existing fd of a pipe
exec(/* some commands */);

//what will be here in order to have the original stdin back?

scanf(...) //continue processing with original stdin.

【问题讨论】:

  • 简单地将dup2() stdin 输入到一个临时文件描述符,然后dup2() 稍后再返回
  • @Ctx 是否可以保留标准输入而不临时复制它?
  • 不要“保留”它,如果可能的话,您可以重新打开它。但是,根据您的标准输入,这可能是不可能的。
  • “exec..()”命令不会返回,除非它们失败。所以 exec 命令后唯一合理的语句是:perror( "exec.. failed" ); 后跟 exit( EXIT_FAILURE );

标签: c unix file-descriptor dup2


【解决方案1】:

原件一旦被覆盖(关闭)就无法恢复。您可以做的是在覆盖之前保存一份副本(当然,这需要提前计划):

int old_stdin = dup(STDIN_FILENO);

dup2(p, STDIN_FILENO);
close(p);               // Usually correct when you dup to a standard I/O file descriptor.

…code using stdin…

dup2(old_stdin, STDIN_FILENO);
close(old_stdin);       // Probably correct
scanf(…);

但是,您的代码提到了 exec(…some commands…); — 如果这是 POSIX execve() 系列函数之一,那么您将无法到达 scanf()(或第二个 dup2())调用,除非 exec*()调用失败。

【讨论】:

  • 如果不将stdin复制到临时fd,你能重新打开stdin吗?
  • 一般来说,没有。原始标准输入可能是管道、套接字或其他一些花哨且短暂的文件类型,它们无法重新打开。另外,您没有可以(重新)打开它的名称。 dup2(p, STDIN_FILENO);操作成功后,/dev/stdin无济于事;它会生成 p 为其打开的文件,而不是原始标准输入。
  • 另外,当我想到它时,请注意,如果您使用文件描述符 dink 而标准 I/O 库从内核读取了一些输入但未交付,您可能会遇到输入缓冲问题到应用程序。 (输出也可能出现类似问题。)
猜你喜欢
  • 1970-01-01
  • 2014-04-07
  • 2018-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多