связь между двумя дочерними процессами с помощью каналов - PullRequest
2 голосов
/ 29 июля 2011

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

Кто-нибудь знает, что не так с моей методологией?

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char** argv) {
    char chld_1_send[20] = "hello from child 1";
    char chld_1_recv[20];
    char chld_2_send[20] = "hi from child 2";
    char chld_2_recv[20];

    int chld_1_outgoing[2];
    int chld_2_outgoing[2];

    pipe(chld_1_outgoing);
    pipe(chld_2_outgoing);

    int chld_1_status, chld_2_status;
    pid_t chld_1, chld_2;

    chld_1 = fork();

    if(chld_1 == 0) {
        chld_2 = fork();
    }

    if(chld_1 == 0 && chld_2 == 0) {
        printf("parent [pid:%d] waiting on both children to finish\n", getpid());

        while(wait(&chld_1_status) != chld_1 && wait(&chld_2_status) != chld_2) {}

        printf("done waiting\n");
    }
    else if(chld_1 != 0 && chld_2 == 0) {
        printf("this is child 1 [pid:%d] with parent [pid:%d]\n", getpid(), getppid());

        write(chld_1_outgoing[1], chld_1_send, strlen(chld_1_send));
        while(read(chld_1_outgoing[0], &chld_1_recv, sizeof(chld_2_recv)) < 0) {}

        printf("child 2 said '%s'\n", chld_1_recv);
        exit(0);
    }
    else if(chld_2 != 0 && chld_1 == 0) {
        printf("this is child 2 [pid:%d] with parent [pid:%d]\n", getpid(), getppid());

        write(chld_2_outgoing[1], chld_2_send, strlen(chld_2_send));
        while(read(chld_2_outgoing[0], &chld_2_recv, sizeof(chld_2_recv)) < 0) {}

        printf("child 1 said '%s'\n", chld_2_recv);

        exit(0);
    }

    printf("both children have terminated successfully\n");

    return 0;
}

Однако выполнение этой команды выводит это на терминал и переходит в бесконечный цикл:

$ this is child 2 [pid:15713] with parent [pid:1]
child 1 said 'hi from child 2'
parent [pid:15714] waiting on both children to finish

Ответы [ 2 ]

2 голосов
/ 30 июля 2011

Ниже приведен простой пример, который, безусловно, можно улучшить, но он поможет вам начать.Также следуйте Link1 и Link2 для получения дополнительной информации.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

/* max  receiving buffer size; Note: no check or enforcement is made on this value*/
#define BUF_SIZE 256

int main()
{
    int pfd1[2];
    int pfd2[2];

    ssize_t numRead = -1;
    /* Note: working under the assumption that the messages
       are of equal length*/
    const char* messageOne = "Hello from child ONE.\n";
    const char* messageTwo = "Hello from child TWO.\n";

    const unsigned int commLen = strlen(messageOne) + 1;

    char buf[BUF_SIZE];

    if (pipe(pfd1) == -1)
    {
        printf("Error opening pipe 1!\n");
        exit(1);
    }

    if (pipe(pfd2) == -1)
    {
        printf("Error opening pipe 2!\n");
        exit(1);
    }

    printf("Piped opened with success. Forking ...\n");

    // child 1
    switch (fork())
    {
        case -1:
            printf("Error forking child 1!\n");
            exit(1);

        case 0:
            printf("\nChild 1 executing...\n");
            /* close reading end of first pipe */
            if (close(pfd1[0]) == -1)
            {
                printf("Error closing reading end of pipe 1.\n");
                _exit(1);
            }
            /* close writing end of second pipe */
            if (close(pfd2[1]) == -1)
            {
                printf("Error closing writing end of pipe 2.\n");
                _exit(1);
            }

            /* write to pipe 1 */
            if (write(pfd1[1], messageOne, commLen) != commLen)
            {
                printf("Error writing to pipe 1.\n");
                _exit(1);
            }

            if (close(pfd1[1]) == -1)
            {
                printf("Error closing writing end of pipe 1.\n");
                _exit(1);
            }

            /* reding from pipe 2 */
            numRead = read(pfd2[0], buf, commLen);
            if (numRead == -1)
            {
                printf("Error reading from pipe 2.\n");
                _exit(1);
            }

            if (close(pfd2[0]) == -1)
            {
                printf("Error closing reding end of pipe 2.\n");
                _exit(1);
            }

            printf("Message received child ONE: %s", buf);
            printf("Exiting child 1...\n");
            _exit(0);

        default:
            break;
    }

    // child 2
    switch (fork())
    {
        case -1:
            printf("Error forking child 2!\n");
            exit(1);
        case 0:
            printf("\nChild 2 executing...\n");
            /* close reading end of second pipe */
            if (close(pfd2[0]) == -1)
            {
                printf("Error closing reading end of pipe 2.\n");
                _exit(1);
            }
            /* close writing end of first pipe */
            if (close(pfd1[1]) == -1)
            {
                printf("Error closing writing end of pipe 1.\n");
                _exit(1);
            }

            /* read from the first pipe */
            if (read(pfd1[0], buf, commLen) == -1)
            {
                printf("Error reading from pipe 1.\n");
                _exit(EXIT_FAILURE);
            }

            if (close(pfd1[0]) == -1)
            {
                printf("Error closing reading end of pipe 1.\n");
                _exit(EXIT_FAILURE);
            }

            /* write to the second pipe */
            if (write(pfd2[1], messageTwo, commLen) != commLen)
            {
                printf("Error writing to the pipe.");
                _exit(EXIT_FAILURE);
            }

            if (close(pfd2[1]) == -1)
            {
                printf("Error closing writing end of pipe 2.");
                _exit(EXIT_FAILURE);
            }

            printf("Message received child TWO: %s", buf);
            printf("Exiting child 2...\n");
            _exit(EXIT_SUCCESS);

        default:
            break;
    }

    printf("Parent closing pipes.\n");

    if (close(pfd1[0]) == -1)
    {
        printf("Error closing reading end of the pipe.\n");
        exit(EXIT_FAILURE);
    }

    if (close(pfd2[1]) == -1)
    {
        printf("Error closing writing end of the pipe.\n");
        exit(EXIT_FAILURE);
    }

    if (close(pfd2[0]) == -1)
    {
        printf("Error closing reading end of the pipe.\n");
        exit(EXIT_FAILURE);
    }

    if (close(pfd1[1]) == -1)
    {
        printf("Error closing writing end of the pipe.\n");
        exit(EXIT_FAILURE);
    }

    printf("Parent waiting for children completion...\n");
    if (wait(NULL) == -1)
    {
        printf("Error waiting.\n");
        exit(EXIT_FAILURE);
    }

    if (wait(NULL) == -1)
    {
        printf("Error waiting.\n");
        exit(EXIT_FAILURE);
    }

    printf("Parent finishing.\n");
    exit(EXIT_SUCCESS);
}
0 голосов
/ 30 июля 2011

Ваша логика обратная для определения того, является ли данный процесс родительским или дочерним процессом.Ребенок получает 0 от fork, а родитель получает пид ребенка.Предположительно, вы хотите, чтобы у обоих детей был один и тот же родитель, и в этом случае первый if должен быть:

if(chld_1 != 0)

И родитель должен быть процессом, в котором оба значения chld_1 и chld_2отличны от нуля:

if(chld_1 != 0 && chld_2 != 0)

Кроме того, вы должны проверять ошибки оба fork s (возврат -1 означает ошибку).

...