Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 使用dup后恢复标准输出_C_Stdout_Dup2 - Fatal编程技术网

C 使用dup后恢复标准输出

C 使用dup后恢复标准输出,c,stdout,dup2,C,Stdout,Dup2,使用fork我创建了一个子对象,并在子对象中使用execl执行ls命令。为了将输出发送到父级,我使用了pipe和dup。然后父级打印输出。代码给出了预期的输出,但当我试图恢复最初保存在stdout_holder中的stdout时,终端上没有打印任何内容(当我使用printf(“hello”)或其下方的execl语句时)。 但是,经过几次观察后,可以发现只有在第一次重定向“1”后未执行任何操作时才会打印hello。(如果我在dup(fd[1],1)之后不做任何事情,只做dup(stdout\u h

使用
fork
我创建了一个子对象,并在子对象中使用
execl
执行
ls
命令。为了将输出发送到父级,我使用了
pipe
dup
。然后父级打印输出。代码给出了预期的输出,但当我试图恢复最初保存在
stdout_holder
中的
stdout
时,终端上没有打印任何内容(当我使用printf(“hello”)或其下方的execl语句时)。 但是,经过几次观察后,可以发现只有在第一次重定向“1”后未执行任何操作时才会打印
hello
。(如果我在
dup(fd[1],1)
之后不做任何事情,只做
dup(stdout\u holder,1)
) 为什么会这样

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<string.h>
int main()
 {int fd[2],stdout_holder;
 char str;
 pid_t pid;
 pipe(fd);
 pid=fork();
 if(pid==0)
  { stdout_holder=dup(1);
    close(fd[0]);
   printf("stdout_holder=%d\n",stdout_holder); 
   fd[1]=dup2(fd[1],1);
   execl("/bin/ls","ls","-l",NULL);
   stdout_holder=dup2(stdout_holder,1);
   printf("hello\n"); //Terminal doesnt show output.
   execl("/bin/ls","ls","-l",NULL); //Terminal doesnt show output

 }
else
 { close(fd[1]);
   wait(&pid);
   while(read(fd[0],&str,1)>0)
   printf("%c",str);
  } 
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{int fd[2],标准输出持有者;
char-str;
pid_t pid;
管道(fd);
pid=fork();
如果(pid==0)
{stdout_holder=dup(1);
关闭(fd[0]);
printf(“stdout\u支架=%d\n”,stdout\u支架);
fd[1]=dup2(fd[1],1);
execl(“/bin/ls”、“ls”、“-l”、NULL);
标准输出单元支架=dup2(标准输出单元支架,1);
printf(“hello\n”);//终端不显示输出。
execl(“/bin/ls”、“ls”、“-l”、NULL);//终端不显示输出
}
其他的
{close(fd[1]);
等待(&pid);
while(读取(fd[0],&str,1)>0)
printf(“%c”,str);
} 
}

存在多个问题:

  • execl()
    不会返回(除非有错误),您需要再次使用
    fork()
    或使用例如system()。 在
    execl
    上,缓冲区不会自动清空,因此 printf输出(至少对我来说)没有到达标准输出

  • printf(“stdout\u holder=…
    ls
    的第一个输出直接到stdout,而不是 通过管道(stdout未更换)。您将 首先需要使用
    dup2()
    ,或者在调用
    dup()
    之前使用
    close(1)


  • 存在多个问题:

  • execl()
    不会返回(除非有错误),您需要再次使用
    fork()
    或使用例如system()。 在
    execl
    上,缓冲区不会自动清空,因此 printf输出(至少对我来说)没有到达标准输出

  • printf(“stdout\u holder=…
    ls
    的第一个输出直接到stdout,而不是 通过管道(stdout未更换)。您将 首先需要使用
    dup2()
    ,或者在调用
    dup()
    之前使用
    close(1)


  • 无论何时调用execl(execv、execlp等),它都会开始执行一个新程序(创建一个新的进程映像)。此新程序的执行会导致进程忘记其以前的进程映像。除非遇到错误,否则execl函数不会返回到同一进程映像

    if(pid==0)
      { stdout_holder=dup(1);
        close(fd[0]);
       printf("stdout_holder=%d\n",stdout_holder); 
       fd[1]=dup2(fd[1],1);
       execl("/bin/ls","ls","-l",NULL); //creates a new process image
       //will never reach here unless there is an error in the execl call
       stdout_holder=dup2(stdout_holder,1);//Line 7
       printf("hello\n");
       execl("/bin/ls","ls","-l",NULL);// Line 9
     }
    
    子进程完成第一个execl调用后,它将终止,因此永远不会到达剩余的代码(从第7行到第9行)。执行新的进程映像将完全更改内存内容,只将参数和环境字符串复制到新位置


    希望这能回答您的问题。

    每当您调用execl(execv、execlp等),它就会开始执行新程序(创建新的进程映像)。此新程序的执行会导致进程忘记其以前的进程映像。除非遇到错误,否则execl函数不会返回到同一进程映像

    if(pid==0)
      { stdout_holder=dup(1);
        close(fd[0]);
       printf("stdout_holder=%d\n",stdout_holder); 
       fd[1]=dup2(fd[1],1);
       execl("/bin/ls","ls","-l",NULL); //creates a new process image
       //will never reach here unless there is an error in the execl call
       stdout_holder=dup2(stdout_holder,1);//Line 7
       printf("hello\n");
       execl("/bin/ls","ls","-l",NULL);// Line 9
     }
    
    子进程完成第一个execl调用后,它将终止,因此永远不会到达剩余的代码(从第7行到第9行)。执行新的进程映像将完全更改内存内容,只将参数和环境字符串复制到新位置

    希望这能回答您的问题。

    如第63行所示,您应该在更改标准输出文件描述符之前保存它:

    int moutfd = dup(STDOUT_FILENO);
    dup2(fd, STDOUT_FILENO);
    
    // Do the going-to-be-buffered jobs
    
    dup2(moutfd, STDOUT_FILENO);
    close(moutfd);
    close(fd);
    
    如第63行所示,在更改标准输出文件描述符之前,应先保存它:

    int moutfd = dup(STDOUT_FILENO);
    dup2(fd, STDOUT_FILENO);
    
    // Do the going-to-be-buffered jobs
    
    dup2(moutfd, STDOUT_FILENO);
    close(moutfd);
    close(fd);
    
    execl()不会在成功时返回,而是替换进程映像。您必须fork()。execl()不会在成功时返回,而是替换进程映像。您必须fork()。谢谢:)关于第二个问题(根据我阅读和尝试的内容),printf后的ls不会转到stdout,因为dup2会自动关闭“1”…dup2(fd1,fd2)…调用此函数时,如果fd2是打开的文件的文件描述符,它会自动关闭它(因此不需要关闭(1)…这就是ls进入管道的原因,我在父进程中打印时得到了输出。谢谢:)关于第二个问题(根据我阅读和尝试的内容),printf后的ls不会转到stdout,因为dup2会自动关闭“1”…dup2(fd1,fd2)…调用时,如果fd2是打开的文件的文件描述符,它会自动关闭它(因此不需要关闭(1)…这就是ls转到管道的原因,我在父进程中打印时得到了输出。谢谢uu:)我实际上是想看一个恢复stdout的例子…如果我用printf语句替换execl语句(比如2)…它们既不会重定向到管道,也不会在终端上打印..在我恢复stdout并给出一个printf语句后,所有语句都会出现在终端上(前面的两个语句和现在给出的一个语句)…我想重定向printf的输出有问题。。?非常感谢你:)编辑:对不起,我的不好…我忘了注释掉父进程中打印前面语句的打印部分。感谢uu:)我实际上正在尝试查看恢复标准输出的示例…如果我用printf语句替换execl语句(例如2)…它们既不会重定向到管道,也不会在终端上打印..在我恢复标准输出并给出一条printf语句后,所有语句都会出现在终端上(之前的两条语句和现在给出的一条语句)