【问题标题】:Redirect forked process output to NULL将分叉的进程输出重定向到 NULL
【发布时间】:2012-03-26 20:06:25
【问题描述】:

我需要创建一个函数,除其他外,它会产生一个子进程。 我想向这个函数传递一个可选的文件描述符列表,以便根据用户需要重定向子进程的输入/输出。

我看到很多人谈论如何使用dup2 来做到这一点,有点像这样:

if( pid < 0 )   // error forking.
{
//...
}
else if( pid != 0 ) // Parent process.
{
    ret = waitpid( pid, &status, 0 );
    return  WEXITSTATUS( status );
}
else    // Child process.
{
    dup2( fd, STDIN_FILENO );   // Clone passed file discriptor.
    close( fd );            // Close the passed one, since we have already cloned.
    execvp( arglist[ 0 ], arglist );
}

好的。所有这些都在互联网上。 我现在的问题是,如何(或最好的方式)重定向到/dev/null

我应该强制用户open( /dev/null) 并将其传递为fd 还是有更好的方法?


编辑:

这并不像我想要的那样漂亮,但我找不到更好的方法,所以我最终将一个文件名数组传递到用户想要重定向的任何地方,分别是 STDIN、STDOUT 和 STDERR:

static int  do_exec( arglist_t arglist, const char *fio[ 3 ] )
{
DEBUG__( OSU_DEBUG_LEVEL_1, "fio = %p\n", fio );

    if ( fio )
    {
        if ( fio[ STDIN_FILENO ] )
        {
            int fd = open( fio[ STDIN_FILENO ], O_RDONLY );

            if ( -1 < fd )
            {
                dup2( fd, STDIN_FILENO );
                close( fd );
            }
        }

        if ( fio[ STDOUT_FILENO ] )
        {
            int fd = open( fio[ STDOUT_FILENO ], O_WRONLY | O_CREAT | O_APPEND );

            if ( -1 < fd )
            {
                dup2( fd, STDOUT_FILENO );
                close( fd );
            }
        }

        if ( fio[ STDERR_FILENO ] )
        {
            int fd = open( fio[ STDERR_FILENO ], O_WRONLY | O_CREAT | O_APPEND );

            if ( -1 < fd )
            {
                dup2( fd, STDERR_FILENO );
                close( fd );
            }
        }
    }

    return  execvp( arglist[ 0 ], arglist );
}
  • 我还没有完全测试它,所以它可能有一些错误。

非常感谢@Zack 和@gbulmer。

【问题讨论】:

    标签: c linux process fork embedded-linux


    【解决方案1】:

    您可以将其作为 API 的约定,即为 fd 传入 -1 意味着使用 /dev/null,然后执行

    // ... same as you have ...
    
    else // Child process
    {
        if (stdin_fd == -1)
            stdin_fd = open("/dev/null", O_RDONLY);
        if (stdin_fd == -1)
            _exit(127);
        dup2(stdin_fd, STDIN_FILENO);
        close(stdin_fd);
    
        // similarly for stdout and stderr
    
        execvp(arglist[0], arglist);
        _exit(127);
    }
    

    (Psst:每次你在括号里面加上空格,上帝就会杀死一只小猫。)

    【讨论】:

    • 我知道这会起作用,但想知道是否有更好的方法来做到这一点。我可以使用下面建议的@gbulmer 之类的文件名,测试字符串是否为NULL,并让我的API 负责打开。这也可以工作,并且对任何文件都没有限制,但仍然会让我觉得它一定是一种更好的方法。真的谢谢!
    • 您认为“更好的方式”是什么样的?
    • 我想看一个不需要显式测试参数、按名称打开文件等的解决方案,但我认为不可能,所以我放弃了。我会按照你的建议去做(见我的编辑)。谢谢!
    【解决方案2】:

    子进程需要知道哪个 fd 用作 dup2 的 oldfd 以及 dup2 到哪个 fd。

    例如,为什么 fd 会被 dup2's 放到 STDIN_FILENO 上?

    孩子需要打开 fd 的信息,以及它应该被复制到的 fd。

    概括地说,为了涵盖处理文件名而不仅仅是处理 fd 的情况,您可以说“/dev/null”,因为它是一个真实的文件名。

    所以只要有一个struct { int oldfd; char* filename; int newfd; } 结构的列表,工作是正常的,/dev/null 不是特例。当 oldfd 为 -1 时,在 newfd 上打开文件名,而不是 dup2'ing 到它上面。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-15
      • 1970-01-01
      • 2021-04-14
      • 1970-01-01
      • 2012-07-04
      • 2012-01-04
      • 1970-01-01
      相关资源
      最近更新 更多