Reputation: 87
I have to create 2 child process and send data from the parent to the two, so I used the pipe
.
If I just use 1 child process and 1 pipe, all works perfectly with fdopen
, fscanf
and fprintf
.
Also, if I create 2 pipe and send data to a single process, still works perfectly.
But, if I create a second process and try to read from the second pipe
, nothing happen.
for example:
int main() {
pid_t pid1, pid2;
int a[2];
pipe(a);
pid1 = fork();
if(pid1 == 0) {
char x,y;
FILE *stream;
stream = fdopen(a[0],"r");
fscanf(stream,"%c",&x);
printf("%c\n", x);
close(a[1]);
close(a[0]);
} else {
int b[2];
pipe(b);
pid2 = fork();
FILE *stream1, *stream2;
close(a[0]);
close(b[0]);
stream1 = fdopen(a[1],"w");
stream2 = fdopen(b[1],"w");
fprintf(stream1, "yo bella zio\n");
fprintf(stream2, "como estas\n");
fflush(stream1);
fflush(stream2);
close(a[1]);
close(b[1]);
waitpid (pid1, NULL, 0);
waitpid (pid2, NULL, 0);
if (pid2 == 0) {
FILE *stream;
close(b[1]);
close(a[1]);
close(a[0]);
stream = fdopen(b[0],"r");
fscanf(stream,"%c",&x);
printf("%c\n", x);
} else {
}
}
}
I really tried all combination. Declare all the pipe together, close or not close pipe. everything but nothing.
Upvotes: 0
Views: 1442
Reputation: 754110
This code fixes the problems identified in my comment and some stray issues.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
pid_t pid1, pid2;
int a[2];
int b[2];
pipe(a);
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, "failed to fork child 1 (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
else if (pid1 == 0)
{
close(a[1]); // Must be closed before the loop
FILE *stream = fdopen(a[0], "r");
if (stream == NULL)
{
fprintf(stderr, "failed to create stream for reading (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
int c;
while ((c = getc(stream)) != EOF)
putchar(c);
//char x;
//fscanf(stream, "%c", &x);
//printf("%c\n", x);
//close(a[0]); -- Bad idea once you've used fdopen() on the descriptor
printf("Child 1 done\n");
exit(0);
}
else
{
pipe(b);
pid2 = fork();
if (pid2 < 0)
{
fprintf(stderr, "failed to fork child 2 (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
else if (pid2 == 0)
{
close(b[1]);
close(a[1]);
close(a[0]);
FILE *stream = fdopen(b[0], "r");
if (stream == NULL)
{
fprintf(stderr, "failed to create stream for reading (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
int c;
while ((c = getc(stream)) != EOF)
putchar(c);
//char x;
//fscanf(stream, "%c", &x);
//printf("%c\n", x);
printf("Child 2 done\n");
exit(0);
}
}
close(a[0]);
close(b[0]);
FILE *stream1 = fdopen(a[1], "w");
if (stream1 == NULL)
{
fprintf(stderr, "failed to create stream for writing (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
FILE *stream2 = fdopen(b[1], "w");
if (stream2 == NULL)
{
fprintf(stderr, "failed to create stream for writing (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
fprintf(stream1, "yo bella zio\n");
fprintf(stream2, "como estas\n");
fflush(stream1); // Not necessary because fclose flushes the stream
fflush(stream2); // Not necessary because fclose flushes the stream
fclose(stream1); // Necessary because child won't get EOF until this is closed
fclose(stream2); // Necessary because child won't get EOF until this is closed
//close(a[1]); -- bad idea once you've used fdopen() on the descriptor
//close(b[1]); -- bad idea once you've used fdopen() on the descriptor
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
printf("All done!\n");
return 0;
}
Note that I changed the child processes so that (a) they explicitly exit in the code block, and (b) made their body into a loop so that all the data sent is printed. That required me to move the close(a[1])
in the first child; otherwise, the loop doesn't terminate because the o/s sees that child 1 has the descriptor open for writing.
When executed on a Mac running macOS 10.13.6 High Sierra (GCC 8.2.0 as the compiler), I get the output:
yo bella zio
Child 1 done
como estas
Child 2 done
All done!
Upvotes: 2