使用fork
我创建了一个孩子,在孩子中我正在使用ls
执行execl
命令。要将输出发送到父级,我使用了pipe
和dup
。父母然后打印输出。代码给出了预期的输出,但是当我尝试恢复最初在stdout
中保存的stdout_holder
时,终端上没有打印任何内容(当我使用printf(“hello”)或execl语句时在它下面)。
然而,在几次观察之后,观察到仅在第一次重定向“1”之后没有做任何事情时才打印hello
。 (如果我在dup(fd[1],1)
之后没有做任何事情,只做dup(stdout_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);
}
}
答案 0 :(得分:0)
有很多问题:
execl()
未返回(除非出现错误),您需要再次fork()
或使用例如系统()。
在execl
上,缓冲区不会自动清空,所以
printf输出(至少对我而言)没有达到标准输出。
printf("stdout_holder= ...
和ls
的第一个输出直接转到stdout,而不是
通过管道(stdout没有被替换)。你会
首先需要使用dup2()
或close(1)
来电前使用dup()
..
答案 1 :(得分:0)
每当您调用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行)。执行新的过程映像会完全更改内存的内容,只将参数和环境字符串复制到新位置。
希望这能回答你的问题。
答案 2 :(得分:0)
在this file的第63行中,您应该在更改之前保存stdout文件描述符:
int moutfd = dup(STDOUT_FILENO);
dup2(fd, STDOUT_FILENO);
// Do the going-to-be-buffered jobs
dup2(moutfd, STDOUT_FILENO);
close(moutfd);
close(fd);