Один дочерний процесс
Основные версии обоих исходных файлов - parent.c
и child.c
.
parent.c
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define SIZE 81
#define EXEC "./child"
int main(int argc, char *argv[])
{
char charMatrix[SIZE] = { 0 };
int matrix[9][9] = { 0 };
if (argc != 2)
{
fprintf(stderr, "Usage: %s matrixfile\n", argv[0]);
exit(EXIT_FAILURE);
}
int fdr = open(argv[1], O_RDONLY);
if (fdr < 0)
{
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
char c;
int k = 0;
while (read(fdr, &c, 1) == 1 && k < (int)sizeof(charMatrix))
{
if (c != ' ' && c != '\n')
charMatrix[k++] = c - '0';
}
close(fdr);
int index = 0;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
matrix[i][j] = charMatrix[index++];
}
printf("Input matrix:\n");
for (int i = 0; i < 9; i++)
{
printf("P: ");
for (int j = 0; j < 9; j++)
printf(" %d", matrix[i][j]);
printf("\n");
}
fflush(stdout); // Make sure output is flushed even it it is going to a pipe
int pipe1[2];
int pipe2[2];
if (pipe(pipe1) == -1 || pipe(pipe2) == -1)
{
perror("Pipe failed");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid < 0)
{
perror("Fork failed");
exit(EXIT_FAILURE);
}
if (pid == 0)
{
dup2(pipe1[0], STDIN_FILENO);
close(pipe1[0]);
close(pipe1[1]);
dup2(pipe2[1], STDOUT_FILENO);
close(pipe2[0]);
close(pipe2[1]);
execl(EXEC, EXEC, NULL);
int errnum = errno;
fprintf(stderr, "Failed to execute '%s' (%d: %s)\n", EXEC, errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
else
{
close(pipe1[0]);
if (write(pipe1[1], charMatrix, sizeof(charMatrix)) != sizeof(charMatrix))
{
perror("failed to write to child");
exit(EXIT_FAILURE);
}
close(pipe1[1]);
close(pipe2[1]);
char result[3];
int nbytes = read(pipe2[0], &result, sizeof(result));
if (nbytes <= 0)
{
perror("Failed to read from pipe");
exit(EXIT_FAILURE);
}
close(pipe2[0]);
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("Child %d exited with status 0x%.4X\n", corpse, status);
printf("Received '%.*s' from child\n", nbytes, result);
}
return(EXIT_SUCCESS);
}
child.c
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
int matrix[9][9];
char charMatrix[81];
fprintf(stderr, "got here\n");
int nbytes = read(STDIN_FILENO, charMatrix, sizeof(charMatrix));
fprintf(stderr, "got %d bytes\n", nbytes);
int index = 0;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
matrix[i][j] = charMatrix[index++];
}
write(STDOUT_FILENO, "a", sizeof(char));
fprintf(stderr, "Ack written to parent\n");
fprintf(stderr, "Child matrix:\n");
for (int i = 0; i < 9; i++)
{
fprintf(stderr, "C: ");
for (int j = 0; j < 9; j++)
fprintf(stderr, " %d", matrix[i][j]);
fprintf(stderr, "\n");
}
return(0);
}
Случайная матрица
6 9 4 5 3 2 6 1 2
2 7 1 5 1 9 1 5 7
1 5 3 1 6 6 7 1 8
6 3 2 4 2 8 9 5 2
2 2 7 9 4 1 3 7 7
3 1 7 8 6 5 5 2 4
6 5 9 1 6 7 7 8 7
5 4 9 5 1 8 9 2 1
3 5 6 8 3 6 9 6 9
Вывод
$ ./parent random.matrix
Input matrix:
P: 6 9 4 5 3 2 6 1 2
P: 2 7 1 5 1 9 1 5 7
P: 1 5 3 1 6 6 7 1 8
P: 6 3 2 4 2 8 9 5 2
P: 2 2 7 9 4 1 3 7 7
P: 3 1 7 8 6 5 5 2 4
P: 6 5 9 1 6 7 7 8 7
P: 5 4 9 5 1 8 9 2 1
P: 3 5 6 8 3 6 9 6 9
got here
got 81 bytes
Ack written to parent
Child matrix:
C: 6 9 4 5 3 2 6 1 2
C: 2 7 1 5 1 9 1 5 7
C: 1 5 3 1 6 6 7 1 8
C: 6 3 2 4 2 8 9 5 2
C: 2 2 7 9 4 1 3 7 7
C: 3 1 7 8 6 5 5 2 4
C: 6 5 9 1 6 7 7 8 7
C: 5 4 9 5 1 8 9 2 1
C: 3 5 6 8 3 6 9 6 9
Child 9498 exited with status 0x0000
Received 'a' from child
$
Два дочерних процесса
Не совсем понятно, почему вы определяете, ноне используйте pipe4
в вашем исправленном коде.Я решил, что так будет проще.При переходе от 1 к 2 процессам соглашения об именах с цифровыми суффиксами становятся скрипучими (но код ниже все еще использует их).Было бы лучше думать с точки зрения массивов.Я пересмотрел дочерние процессы для отправки больших сообщений и родительский код для их получения - это дает лучшую идентификацию того, что происходит.Вывод от детей может чередоваться.
Мне не ясно, как вы предполагали трио работающих труб.Используя четыре трубы, трубы 1 и 2 соединяются с ребенком 1;трубы 3 и 4 к ребенку 2. Труба с нечетным номером передает информацию ребенку;труба четного числа передает информацию от ребенка.Есть множество вызовов на close()
.
pipe47.c
/* SO 5609-3694 */
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define SIZE 81
#define EXEC1 "./child2"
#define EXEC2 "./child2"
int main(int argc, char *argv[])
{
char charMatrix[SIZE] = { 0 };
int matrix[9][9] = { 0 };
if (argc != 2)
{
fprintf(stderr, "Usage: %s matrix file \n", argv[0]);
exit(EXIT_FAILURE);
}
int fdr = open(argv[1], O_RDONLY);
if (fdr < 0)
{
perror("failed to open input or output files");
exit(EXIT_FAILURE);
}
char c;
int k = 0;
while (read(fdr, &c, 1) == 1 && k < (int)sizeof(charMatrix))
{
if (c != ' ' && c != '\n')
charMatrix[k++] = c - '0';
}
close(fdr);
int index = 0;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
matrix[i][j] = charMatrix[index++];
}
printf("Input matrix:\n");
for (int i = 0; i < 9; i++)
{
printf("P: ");
for (int j = 0; j < 9; j++)
printf(" %d", matrix[i][j]);
printf("\n");
}
fflush(stdout); // Making sure output is flushed even if it is going to a pipe
int pipe1[2];
int pipe2[2];
int pipe3[2];
int pipe4[2];
if (pipe(pipe1) == -1 || pipe(pipe2) == -1 || pipe(pipe3) == -1 || pipe(pipe4) == -1) // pipe validation
{
perror("Pipe failed");
exit(EXIT_FAILURE);
}
pid_t fChild = fork();
if (fChild < 0)
{
perror("Fork failed (child 1)");
exit(EXIT_FAILURE);
}
if (fChild == 0)
{
dup2(pipe1[0], STDIN_FILENO);
dup2(pipe2[1], STDOUT_FILENO);
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
close(pipe3[0]);
close(pipe3[1]);
close(pipe4[0]);
close(pipe4[1]);
execl(EXEC1, EXEC1, NULL);
int errnum = errno;
fprintf(stderr, "Failed to execute '%s' (1) (%d: %s)\n", EXEC1, errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
pid_t sChild = fork();
if (sChild < 0)
{
perror("Fork failed (child 2)");
exit(EXIT_FAILURE);
}
if (sChild == 0)
{
dup2(pipe3[0], STDIN_FILENO);
dup2(pipe4[1], STDOUT_FILENO);
close(pipe1[0]);
close(pipe1[1]);
close(pipe2[0]);
close(pipe2[1]);
close(pipe3[0]);
close(pipe3[1]);
close(pipe4[0]);
close(pipe4[1]);
execl(EXEC2, EXEC2, NULL);
int errnum = errno;
fprintf(stderr, "Failed to execute '%s' (2) (%d: %s)\n", EXEC2, errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
close(pipe1[0]);
close(pipe2[1]);
close(pipe3[0]);
close(pipe4[1]);
if (write(pipe1[1], charMatrix, sizeof(charMatrix)) != sizeof(charMatrix))
{
perror("failed to write to child 1");
exit(EXIT_FAILURE);
}
close(pipe1[1]);
if (write(pipe3[1], charMatrix, sizeof(charMatrix)) != sizeof(charMatrix))
{
perror("failed to write to child 2");
exit(EXIT_FAILURE);
}
close(pipe3[1]);
char result1[64];
int nbytes1 = read(pipe2[0], &result1, sizeof(result1));
close(pipe2[0]);
if (nbytes1 <= 0)
{
perror("Failed to read from child 1");
exit(EXIT_FAILURE);
}
char result2[64];
int nbytes2 = read(pipe4[0], &result2, sizeof(result2));
close(pipe4[0]);
if (nbytes2 <= 0)
{
perror("Failed to read from child 2");
exit(EXIT_FAILURE);
}
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("Child %d exited with status 0x%.4X\n", corpse, status);
printf("Received '%.*s' from child 1\n", nbytes1, result1);
printf("Received '%.*s' from child 2\n", nbytes2, result2);
return(EXIT_SUCCESS);
}
child2.c
/* SO 5609-3694 */
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
int main(void)
{
int matrix[9][9];
char charMatrix[81];
int pid = getpid();
fprintf(stderr, "PID %d: got here\n", pid);
int nbytes = read(STDIN_FILENO, charMatrix, sizeof(charMatrix));
fprintf(stderr, "PID %d: got %d bytes\n", pid, nbytes);
int index = 0;
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
matrix[i][j] = charMatrix[index++];
}
//write(STDOUT_FILENO, "a", sizeof(char));
printf("PID %d: message received", pid);
fprintf(stderr, "PID %d: Ack written to parent\n", pid);
fprintf(stderr, "PID %d: Child matrix:\n", pid);
for (int i = 0; i < 9; i++)
{
fprintf(stderr, "PID %d: ", pid);
for (int j = 0; j < 9; j++)
fprintf(stderr, " %d", matrix[i][j]);
fprintf(stderr, "\n");
}
return(0);
}
Выход
Обратите внимание, чтовыходные данные двух детей перемежаются друг с другом.Можно было бы разработать механизмы, чтобы этого избежать.
$ ./pipe47 random.matrix
Input matrix:
P: 6 9 4 5 3 2 6 1 2
P: 2 7 1 5 1 9 1 5 7
P: 1 5 3 1 6 6 7 1 8
P: 6 3 2 4 2 8 9 5 2
P: 2 2 7 9 4 1 3 7 7
P: 3 1 7 8 6 5 5 2 4
P: 6 5 9 1 6 7 7 8 7
P: 5 4 9 5 1 8 9 2 1
P: 3 5 6 8 3 6 9 6 9
PID 11903: got here
PID 11903: got 81 bytes
PID 11903: Ack written to parent
PID 11903: Child matrix:
PID 11903: 6 9 4 5 3 2 6 1 2
PID 11903: 2 7 1 5 1PID 11904: got here
9 1 5 7
PID 11903: 1 5 3 1PID 11904: got 81 bytes
6 6 7 1 8
PID 11903: 6 3 2PID 11904: Ack written to parent
4PID 11904: Child matrix:
2PID 11904: 8 6 9 9 5 4 2 5
3PID 11903: 2 2 6 2 1 7 2 9 4 1
3PID 11904: 7 2 7 7
1PID 11903: 5 3 1 1 9 7 1 8 5 6 7 5
5PID 11904: 2 1 4 5
3PID 11903: 1 6 6 5 6 9 7 1 1 6 8 7
7PID 11904: 8 6 7 3
2PID 11903: 4 5 2 4 8 9 9 5 5 1 2 8
9PID 11904: 2 2 1 2
7PID 11903: 9 3 4 5 1 6 3 8 7 3 7 6
9PID 11904: 6 3 9 1
7 8 6 5 5 2 4
PID 11904: 6 5 9 1 6 7 7 8 7
PID 11904: 5 4 9 5 1 8 9 2 1
PID 11904: 3 5 6 8 3 6 9 6 9
Child 11903 exited with status 0x0000
Child 11904 exited with status 0x0000
Received 'PID 11903: message received' from child 1
Received 'PID 11904: message received' from child 2
$