使用execvp和dup2 syscalls后写入终端的问题

问题描述

第15行{ printf("This goes to the terminal\n"); }没有在终端或文件中的任何地方打印。

//inputs   argc = 3 :- ./executable_file  output_file  command
    int main(int argc,char **argv)
    {
        if(argc < 3)
        {
            return 0;
        }
        int stdout_copy = dup(1);
        int fd = open(argv[1],O_CREAT | O_RDWR | O_Trunc,0644);
        if (fd < 0)
        {
            printf("ERROR\n");
            return 0;
        }
        printf("This goes to the standard output(terminal).\n");
        printf("Now the standard output will go to \"%s\" file  .\n",argv[1]);
        dup2(fd,1);
        printf("This output goes to \"%s\"\n",argv[1]);
        close(fd);
        execvp(argv[2],argv+2);
        dup2(stdout_copy,1);
        printf("This goes to the terminal\n");
        return 0;
    }

一个问题的道歉: 我真的很抱歉,这是我分析错误。 特别感谢您提供所有答案和提示

解决方法

使用execvp和dup2系统调用后写入终端的问题

都不:

    execvp(argc[2],argc+2);
    dup2(stdout_copy,1);
    printf("This goes to the terminal\n");

或者:

    dup2(stdout_copy,1);
    execvp(argc[2],argc+2);
    printf("This goes to the terminal\n");

...如果对stdout的调用成功,将输出到execvp(argc[2],argc+2);
但是,如果失败,两者都将输出到stdout
(除非命令行参数不正确,否则dup2()可能与无法输出到stdout无关。请参见下面的其他内容,以了解如何进行检查。)

在这里阅读所有相关内容:execvp
简而言之,execvp()用新进程替换了当前进程。如果成功,则当前过程不再是您在终端上查看的过程。仅当不成功成功时,才会执行其后的命令。

以下建议并非完全正确,但仍然很重要...

更改:

int main(int argv,char **argc)

收件人:

int main(int argc,char **argv)  //or  int main(int argc,char *argv[]),either are fine.

这将是看到正常行为的基础。其他任何事情都会使您的代码的未来维护者以及试图了解您在此处所做的工作的人感到困惑。
请记住,argc用于命令行参数的计数,而argv是用于存储它们的 vector ,这些名称很容易记住。>

此外,您的代码没有显示任何迹象表明您正在检查/验证这些参数,但鉴于程序的性质,应在继续操作之前对其进行验证。例如:

//verify required number of command line arguments was entered
if(argc <!= 3)//requires at least one additional command line argument
{
    printf("Usage: prog.exe [path_filename]\nInclude path_filename and try again.\nProgram will exit.");
    return 0;
}
//check if file exists before going on
if( access( argv[1],F_OK ) != -1 ) 
{
     // file exists
} else {
     // file doesn't exist
}
//do same for argv[2]

(在Linux环境中检查文件的第二个示例来自here

BTW,了解传递到程序中的命令行参数,将有助于在此处提供更明确的答案。它们的语法和内容以及所引用的文件是否存在,确定了对execvp的调用的行为。

建议

  • 通常总是查看具有它们的函数的返回值。但是由于execvp的独特行为,如果成功,它将不返回;如果失败,它将始终返回-1。因此,在这种情况下,请特别注意错误指示的errno的值,所有这些错误都在上面的链接中涵盖了。

  • 正如注释中提到的(在两个地方),在解释标准fflush(stdout)和文件描述符I/O时以及之前使用I/O清空缓冲区是一个好主意。使用任何exec*()系列通话。

  • 花些时间阅读功能的 man 页-使用的shell命令。这样可以节省时间,并在调试会话期间为您提供指导。