execv调用后打开文件句柄会发生什么? (C ++)

时间:2010-09-28 18:51:28

标签: c++ linux process

在Linux上,我有一些C ++代码,我想要执行另一个应用程序。该程序将一些数据输出到stderr。因此,我通过使用stderr作为流参数调用freopen()来重定向stderr。问题是,我想将stderr重定向到另一个运行的进程。

以下是我正在使用的方案。我fork()当前的进程;在子进程中,我重定向了stderr;然后我execv()运行单独的应用程序。

首先,我设置了一个Sentry来重定向stderr输出。这是代码:

class StderrSentry {
public:
  StderrSentry() {
    freopen( "NUL", "wt", stderr );
  }
  ~StderrSentry() {
    fclose( stderr );
  }
};

然后在代码中:

pid_t pid = fork();
int retval=-1;

if( pid < 0 ) {
  success = false;
}
else if( ! pid ) {  // child process
  StderrSentry stdErrSentry;   // REDIRECTING STDERR HERE!
  pid_t chid = setsid();
  if (chid == -1 ) {
    exit(-1);
  }
  else {
    //  HERE IS THE execv() call:
    if( execv(command[0].c_str(), const_cast<char**>(&c_args[0])) < 0 ) {
      exit( -1 );
    }
  }
}
// ... else etc...

一旦execv()调用用指定的一个替换当前进程,stderr重定向在技术上是否仍然有效?

这实际上是按照我的意愿行事,但它是侥幸,还是这样做的?

我无法激活execv中运行的应用程序中的stderr重定向,因为它不是我的代码。

感谢您提供任何相关信息。

3 个答案:

答案 0 :(得分:2)

使用操作文件描述符(open,close,dup2)的操作系统原语比使用freopen和朋友更通常更安全,但是,这应该可行,并且是shell管道的实现方式。 execve将所有打开的文件打开,除非它们已被标记为F_CLOEXEC。

答案 1 :(得分:1)

如果文件描述符没有O_CLOEXEC标志(参见man 2 open),它们应该持久存在于exec中。此标志仅在内核2.6.23及更高版本中可用,因此如果您使用的是较旧的发行版,则该标记将不可用。

答案 2 :(得分:0)

重定向非常有效。 execv调用会更改过程映像,但文件描述符保持不变。