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语句后,所有语句都会出现在终端上(之前的两条语句和现在给出的一条语句)