общение между отцом и ребенком dup () - PullRequest
1 голос
/ 11 мая 2019

Мне очень трудно понять проблему общения между отцом и ребенком. когда я запускаю основную программу, кажется, ничего не происходит. Я искал в Интернете решение, и пока мне ничего не помогло. я знаю, что выложил здесь много кода, но из моего старого поста об одной и той же проблеме люди посылают меня читать человека снова и снова, но все еще , что-то здесь не так, и я не знаю что именно . Я надеюсь, что вы, ребята, можете помочь мне

#include <stdio.h>
#include <stdlib.h> //for exit
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> //for sleep(),execvp()
#include <ctype.h>
#include <fcntl.h>
#define IN 0
#define OUT 1
#define SIZE 81
#define EXEC "./child"

int main(int argc, char * argv[])
{
    int fd[2];
    int fdr;   // file descriptors
    int i;
    char result[3];
    pid_t pid;
    char charMatrix[SIZE] ={ 0 };
    int matrix[9][9]={0};
    if (argc < 2)
    {

        printf("No files added, abort program\n");
        exit(EXIT_FAILURE);
    }
    if (pipe(fd) == -1)
    {
        printf("Pipe Failed");
        return 1;
    }
    fdr = open(argv[1], O_RDONLY);   // open files
    if (fdr < 0)
    { //validation for error
        perror("failed to open input or output files");
        exit(EXIT_FAILURE); 
    }
    char c;

    charMatrix[81] = '\0';
    i=0;
    int j=0;
    while (read(fdr, &c, 1))          // read/write a single char
    {                                  // from/to the files
        if (c != ' ' && c != '\n')
        {
            charMatrix[i++]=c-'0';

        }


    }
    close(fdr);   // close the file
    int index=0;    //convert to matrix
    for (i = 0; i < 9; i++) { /* Iterate of each row */
            for (j = 0; j < 9; j++) { /* In each row, go over each col element  */
                matrix[i][j]=charMatrix[index++];
            }
        }
            for (i = 0; i < 9; i++) {//  Iterate of each row
            for (j = 0; j < 9; j++) {  //In each row, go over each col element
                printf("%d ", matrix[i][j]);//  Print each row element
            }
            printf("\n");//  Finish a row, start a new line
            }
    pid = fork();
    if (pid < 0)
    {
        fputs("error in fork", stderr);
        exit(EXIT_FAILURE);
    }
    //child
     if(pid == 0)
     {
                        close(fd[0]);
                close(STDOUT_FILENO);
                dup(fd[1]);
                        execl(EXEC, charMatrix, NULL);


     }
    //parent
     else{

        close(fd[1]);
        close(STDIN_FILENO);
        dup(fd[0]);
        read(fd[0], &result, sizeof(result));
        wait(NULL);

     }





    exit(EXIT_SUCCESS);
}

файл для exec

#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char * argv[]){

    int matrix[9][9];
    char charMatrix[81];
    char ans;
        int i, j;
        printf("got here");
        read(0,&charMatrix,sizeof(charMatrix));
    int index=0;    //convert to matrix
    for (i = 0; i < 9; i++) { /* Iterate of each row */
            for (j = 0; j < 9; j++) { /* In each row, go over each col element  */
                matrix[i][j]=charMatrix[index++];
            }
        }
    write(4, "a", sizeof(char));
    for (i = 0; i < 9; i++) { /* Iterate of each row */
        for (j = 0; j < 9; j++) { /* In each row, go over each col element  */
            printf("%d ", matrix[i][j]); /* Print each row element */
        }
        printf("\n"); /* Finish a row, start a new line */
    }
    exit(0);
}

После предложенного решения я попытался добавить еще одного ребенка, но все равно ошибся. вот код и вид объяснения, как я это вижу

  dup2(pipe1[0], STDIN_FILENO); //makes the input( 0 in the stack) to the pipe1[0] which means point to its 
    close(pipe1[0]);
    close(pipe1[1]); //closing before pointes
    dup2(pipe2[1], STDOUT_FILENO); //makes the output (1 in the stack) to point pip1[1]
    close(pipe2[0]);
    close(pipe2[1]);//closing 
    execl(EXEC, EXEC, NULL);//exec

Я пытался сделать то же самое с другим ребенком с новой трубкой, но безуспешно. я отправляю папе pipe1 на ответ pipe3 второго ребенка

// --------------------------------------------- ---------------------- //

#define SIZE 81
#define EXEC "./child"
#define EXEC2 "./child2"
int main(int argc, char *argv[])
{
    char charMatrix[SIZE] = { 0 };
    int matrix[9][9] = { 0 };
    char chilesStatus[3]={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 validation
    {
        perror("Pipe failed");
        exit(EXIT_FAILURE);
    }

    pid_t fChild = fork();
    if (fChild < 0)
    {
        perror("Fork failed");
        exit(EXIT_FAILURE);
    }

    if (fChild == 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
    {
        pid_t sChild = fork();
        if(sChild==0)
        {
                dup2(pipe2[0], STDIN_FILENO);
                    close(pipe2[0]);
                    close(pipe2[1]);
                    dup2(pipe3[1], STDOUT_FILENO);
                    close(pipe3[0]);
                    close(pipe3[1]);
                    execl(EXEC2, EXEC2, NULL);
                    int errnum = errno;
                    fprintf(stderr, "Failed to execute '%s' (%d: %s)\n", EXEC, errnum, strerror(errnum));
                    exit(EXIT_FAILURE);
        }
        else
        {

        }
    close(pipe2[0]);
        close(pipe1[0]);
        if (write(pipe1[1], charMatrix, sizeof(charMatrix)) != sizeof(charMatrix))
        {
            perror("failed to write to child");
            exit(EXIT_FAILURE);
        }
    if (write(pipe1[2], charMatrix, sizeof(charMatrix)) != sizeof(charMatrix))
        {
            perror("failed to write to child");
            exit(EXIT_FAILURE);
        }
        close(pipe1[1]);
        close(pipe2[1]);
    close(pipe3[1]);
        char result[3];
        int nbytes = read(pipe2[0], &result, sizeof(result));
    int nbytes2 = read(pipe3[0], &result, sizeof(result));
        if (nbytes <= 0 ||nbytes2 <= 0) 
        {
            perror("Failed to read from pipe");
            exit(EXIT_FAILURE);
        }

        close(pipe2[0]);
    close(pipe3[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);
}

1 Ответ

0 голосов
/ 12 мая 2019

Один дочерний процесс

Основные версии обоих исходных файлов - 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
$
...