Этот код исправляет проблемы, указанные в моем комментарии , и некоторые странные проблемы.
#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;
}
Обратите внимание, что я изменил дочерние процессы так, чтобы (а) они явно выходили из блока кода, и (б) превращали свое тело в цикл, так что все отправленные данные печатались. Это потребовало от меня переместить close(a[1])
у первого ребенка; в противном случае цикл не завершается, потому что операционная система видит, что дочерний элемент 1 имеет дескриптор, открытый для записи.
При выполнении на Mac с MacOS 10.13.6 High Sierra (GCC 8.2.0 в качестве компилятора) я получаю вывод:
yo bella zio
Child 1 done
como estas
Child 2 done
All done!