Reputation: 382
Edit: Do not try connecting the end of a pipe to stdout. Connect the input of a pipe to stdout, and the output of the pipe to stdin.
I want to pipe the stdout of a child process to the stdout of its mother using pipe() and dup2(). In my example, I try and print a string in the child, which has its stdout redirect to the pipe; and then have the string appear in the stdout of the Mother. However, the output never appears in the stdout of the mother process. What is going on?
Code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
// This program should print 1, 2 and 4; but only prints 1 and 4.
int stdout_cpy = dup(1);
printf("1. stdout working\n");
int pipe1[2];
pipe(pipe1);
int pid = fork();
if (pid == 0) {
// child
dup2(pipe1[1], 1); // stdout out to pipe in
close(pipe1[0]);
fprintf(stdout, "2. This should print in the mother's stdout\n");
exit(0);
} else {
// mother
close(pipe1[1]);
dup2(pipe1[0], 1); // stdout from pipe out
}
/* 2. should print in parent's stdout... */
int status;
while (wait(&status) > 0);
printf("3. This should not print\n");
dup2(stdout_cpy, 1);
close(pipe1[0]);
printf("4. stdout redirected, done\n");
return 0;
}
Output
1. stdout working
4. stdout redirected, done
Upvotes: 1
Views: 4407
Reputation: 753725
Here is a working version of your code. For the output from the child to appear, the parent must read it from the pipe and then write that to its own standard output, which is what this code does. If nothing reads from the pipe, the output written to the pipe won't appear anywhere. This change makes the duplicated standard output basically irrelevant.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int stdout_cpy = dup(1); // Mostly irrelevant
printf("1. stdout working\n");
int pipe1[2];
pipe(pipe1);
int pid = fork();
if (pid == 0)
{
// child at work
dup2(pipe1[1], 1); // stdout out to write end of pipe
close(pipe1[0]); // Close both ends of the pipe!
close(pipe1[1]); // Close both ends of the pipe!
printf("2. This should be read by parent from stdin and be printed to the parent's stdout\n");
exit(0);
}
/* Parent at work */
dup2(pipe1[0], 0); // stdin from from read end of pipe
close(pipe1[0]); // Close both ends of the pipe!
close(pipe1[1]); // Close both ends of the pipe!
// Read data written on pipe by child, and write to stdout
char buffer[512];
int nbytes = read(0, buffer, sizeof(buffer));
if (nbytes > 0)
write(1, buffer, nbytes);
/* 2. should print in parent's stdout... */
int status;
int corpse;
while ((corpse = wait(&status)) > 0)
printf("%d: child %d exited with status 0x%.4X\n", (int)getpid(), corpse, status);
printf("3. This should print too\n");
dup2(stdout_cpy, 1); // Mostly irrelevant
//close(pipe1[0]); // Long since closed
close(stdout_cpy); // No longer needed (closed on exit anyway)
printf("4. stdout redirected, done\n");
return 0;
}
Sample output:
1. stdout working
2. This should be read by parent from stdin and be printed to the parent's stdout
8008: child 8009 exited with status 0x0000
3. This should print too
4. stdout redirected, done
Alternatively, if you just want the child's output to appear on the same device as the parent's output, simply don't use a pipe at all; the child will inherit the parent's standard output and can write to it without any extra help.
Upvotes: 1