将分叉进程输出重定向为NULL

时间:2012-03-26 20:06:26

标签: c linux process fork embedded-linux

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

我见过很多人在讨论如何使用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。

2 个答案:

答案 0 :(得分:4)

您可以将其作为API的惯例,传递-1以获取fd意味着使用/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);
}

(诗篇:每当你在括号内放置空格时,上帝会杀死一只小猫。)

答案 1 :(得分:1)

子进程需要知道哪个fd用作dup2的oldfd和用于复制到f2的fd。

例如,为什么fd会被复制到STDIN_FILENO上?

孩子需要打开fd的信息,并且fd应该重复上传。

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

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