[英]Redirect child process's stdin and stdout to pipes
EDIT: The solution is 编辑:解决方案是
int c1=dup2(pipes[0][1],STDOUT_FILENO);
int c2=dup2(pipes[1][0],STDIN_FILENO);
setvbuf(stdout,NULL,_IONBF,0);
It is SETVBUF to set stdout to be non-buffered. 将标准输出设置为非缓冲是SETVBUF。 Even though I was printing the newline character if the destination is not an actual screen, I guess, it becomes buffered. 即使目标不是实际的屏幕,即使我正在打印换行符,我也认为它已被缓冲。
EDIT: When I put fflush(stdout) after LINE 1 and fflush(fout) after LINE 4 it works as expected. 编辑:当我将fflush(stdout)放在LINE 1之后,将fflush(fout)放在LINE 4之后,它可以按预期工作。 However, it does not work without the fflush(stdout) after LINE 1. The problem is that I would not be able to put fflush in the program which I am planning to run. 但是,如果没有LINE 1之后的fflush(stdout) ,它将无法正常工作。问题是我无法将fflush放入我计划运行的程序中。
I am trying to start another program from my process. 我试图从我的程序中启动另一个程序。 I don't have access to its code but I know it uses stdin and stdout for user interaction. 我无权访问其代码,但我知道它使用stdin和stdout进行用户交互。 I am trying to start that program by creating 2 pipes, fork-ing and redirecting the child's stdin/stdout to the proper pipe ends. 我试图通过创建2个管道,分叉并将孩子的stdin / stdout重定向到适当的管道末端来启动该程序。 The points is that the parent should be able communicate with the child via file descriptors, while its stdin/stdout should be intact. 重点是,父级应该能够通过文件描述符与子级进行通信,而其stdin / stdout应该是完整的。 The POPEN syscall only opens unidirectional pipe. POPEN syscall仅打开单向管道。 The following code almost works. 以下代码几乎可以正常工作。
There are 4 lines marked as LINE 1..4. 有4行标记为LINE 1..4。
LINE 1 is child sending to pipe, LINE 2 is child receiving from pipe, LINE 3 is parent sending to pipe, LINE 4 is parent receiving from pipe, LINE 1是向管道发送的子项,LINE 2是从管道接收的子项,LINE 3是向管道发送的父项,LINE 4是从管道接收的父项,
This is just a toy example to make sure things work. 这只是确保事情正常的玩具示例。 The issue is that is all 4 lines LINE1..4 are uncommented the output I see on the terminal is 问题是所有4行LINE1..4都未注释,我在终端上看到的输出是
PARENT1: -1
FD: 1 0 4 5 0 1
DEBUG1: 0
DEBUG2: 0
While if LINE 1 and LINE 3 are uncommented only I see a continuous stream of data. 如果仅取消注释LINE 1和LINE 3,我会看到连续的数据流。 Same happens if if only LINE 2 and LINE 4 are uncommented. 如果仅注释第2行和第4行,则会发生同样的情况。 However, I want a full bidirectional communication. 但是,我想要一个完整的双向通信。 Also adding the commented SLEEP does not change the behavior. 同时添加注释的SLEEP不会更改行为。
What could be the issue here. 这里可能是什么问题。 I wonder why is there no bidirectional POPEN. 我想知道为什么没有双向POPEN。
int pid;
int pipes[2][2];
pipe(pipes[0]);
pipe(pipes[1]);
pid=fork();
if(pid==0)
{
//usleep(1000000);
close(pipes[0][0]);
close(pipes[1][1]);
int c1=dup2(pipes[0][1],STDOUT_FILENO);
int c2=dup2(pipes[1][0],STDIN_FILENO);
//int c2=dup2(STDIN_FILENO,pipes[1][0]);
fprintf(stderr,"FD: %d %d %d %d %d %d\n",c1,c2,pipes[0][1],pipes[1][0],STDIN_FILENO,STDOUT_FILENO);
//FILE*fout=fdopen(pipes[0][1],"w");
//FILE*fin =fdopen(pipes[1][0],"r");
while(1)
{
static int c1=0;
fprintf(stderr,"DEBUG1: %d\n",c1);
printf("%d\n",c1); // LINE 1
fprintf(stderr,"DEBUG2: %d\n",c1);
scanf("%d",&c1); // LINE 2
fprintf(stderr,"DEBUG3: %d\n",c1);
c1++;
}
//fclose(fout);
//fclose(fin);
return 0;
}
close(pipes[0][1]);
close(pipes[1][0]);
char buffer[100];
FILE*fin=fdopen(pipes[0][0],"r");
FILE*fout=fdopen(pipes[1][1],"w");
while(1)
{
int c1=-1;
printf("PARENT1: %d\n",c1);
fscanf(fin,"%d",&c1); // LINE 3
printf("Recv: %d\n",c1);
fprintf(fout,"%d\n",c1+1); // LINE 4
printf("PARENT3: %d\n",c1+1);
}
fclose(fin);
fclose(fout);
Your code is quite long so I'm not sure that I have understand everything but why you don't use select ? 您的代码很长,因此我不确定我是否了解所有内容,但是为什么不使用select ? Do you want to redirect the output of the child in a tird process or use it in your parent process ? 您是要在第三个进程中重定向子级的输出,还是在父级进程中使用它?
The following exemple is with cat in the child process. 以下示例与子进程中的cat有关。
#include <unistd.h>
#include <stdlib.h>
int main()
{
pid_t pid;
int p[2];
pipe(p);
pid = fork();
if (pid == 0)
{
dup2(p[1], 1); // redirect the output (STDOUT to the pipe)
close(p[0]);
execlp("cat", "cat", NULL);
exit(EXIT_FAILURE);
}
else
{
close(p[1]);
fd_set rfds;
char buffer[10] = {0};
while (1)
{
FD_ZERO(&rfds);
FD_SET(p[0], &rfds);
select(p[0] + 1, &rfds, NULL, NULL, NULL); //wait for changes on p[0]
if(FD_ISSET(p[0], &rfds))
{
int ret = 0;
while ((ret = read(p[0], buffer, 10)) > 0) //read on the pipe
{
write(1, buffer, ret); //display the result
memset(buffer, 0, 10);
}
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.