Несколько труб 1-к-1 в C - PullRequest
       20

Несколько труб 1-к-1 в C

0 голосов
/ 03 марта 2019

Возможно ли в C иметь несколько одновременных каналов 1-к-1?Мой пример использования следующий:

  1. Родитель создает x дочерних процессов с использованием fork ()
  2. Родитель создает x каналов, по одному для каждого дочернего элемента
  3. Каждыйдочерний объект пишет в соответствующий канал, затем закрывает его.
  4. Родитель читает из каналов, а затем закрывает их.

Моя текущая попытка черновика заключается в следующем, однако у меня есть сомнения относительно его функциональности.:

// Create x pipes
int fd[2*x];
pipe(fd);

// In child i do (i from 0 to x-1 inclusive):
close(fd[2*i]);
write(fd[2*i +1], .....);
close(fd[2*i +1]);

// In parent do:
wait() // wait for children to finish
// while any pipe has content do:
// For each i from 0 to x-1 inclusive:
close(fd[2*i +1]);
read(fd[2*i], .....);
close(fd[2*i]);

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

1 Ответ

0 голосов
/ 03 марта 2019

Этот код более или менее делает то, что вы хотите.Он использует код сообщения об ошибках, который доступен в моем SOQ (вопросы о переполнении стека) на GitHub в виде файлов stderr.c и stderr.h в подкаталоге src / libsoq .

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

enum { NUM_CHILDREN = 5 };
enum { MSG_BUFFSIZE = 64 };
static void be_childish(int kid, int *fd);

int main(int argc, char **argv)
{
    int fd[2 * NUM_CHILDREN];
    int pid[NUM_CHILDREN];

    err_setarg0(argv[0]);
    err_setlogopts(ERR_PID);

    if (argc != 1)
        err_usage("");

    for (int i = 0; i < NUM_CHILDREN; i++)
    {
         if (pipe(&fd[2 * i]) != 0)
             err_syserr("failed to create pipe for child %d: ", i);
    }

    for (int i = 0; i < NUM_CHILDREN; i++)
    {
        if ((pid[i] = fork()) < 0)
            err_syserr("failed to fork child %d: ", i);
        else if (pid[i] == 0)
            be_childish(i, fd);
        else
        {
            printf("Child %d has PID %d\n", i, pid[i]);
            fflush(stdout);
        }
    }

    char buffer[MSG_BUFFSIZE];
    for (int i = 0; i < NUM_CHILDREN; i++)
    {
        close(fd[2 * i + 1]);
        int pipe_in = fd[2 * i + 0];
        int nbytes = read(pipe_in, buffer, sizeof(buffer));
        if (nbytes < 0)
            err_syserr("failed to read from FD %2d: ", pipe_in);
        printf("Got %2d bytes [%.*s] from FD %2d, PID %d\n",
               nbytes, nbytes, buffer, pipe_in, pid[i]);
        close(pipe_in);
    }

    for (int i = 0; i < NUM_CHILDREN; i++)
    {
        int status;
        int corpse = wait(&status);
        if (corpse > 0)
            printf("Child with PID %d exited with status 0x%.4X\n", corpse, status);
        else
            err_syserr("Failed to wait for dead children: ");
    }

    return 0;
}

static void be_childish(int kid, int *fd)
{
    for (int i = 0; i < kid; i++)
    {
        close(fd[2 * i + 0]);
        close(fd[2 * i + 1]);
    }

    close(fd[2 * kid + 0]);
    int estat = kid + 32;

    char buffer[MSG_BUFFSIZE];
    int nbytes = snprintf(buffer, sizeof(buffer),
                          "Child %d (PID %d) exiting with status %d",
                          kid, (int)getpid(), estat);
    int pipe_out = fd[2 * kid + 1];
    if (write(pipe_out, buffer, nbytes) != nbytes)
        err_syserr("failed to write to parent: ");
    close(pipe_out);
    exit(estat);
}

Пробный прогон:

Child 0 has PID 36957
Child 1 has PID 36958
Child 2 has PID 36959
Child 3 has PID 36960
Child 4 has PID 36961
Got 42 bytes [Child 0 (PID 36957) exiting with status 32] from FD  3, PID 36957
Got 42 bytes [Child 1 (PID 36958) exiting with status 33] from FD  5, PID 36958
Got 42 bytes [Child 2 (PID 36959) exiting with status 34] from FD  7, PID 36959
Got 42 bytes [Child 3 (PID 36960) exiting with status 35] from FD  9, PID 36960
Got 42 bytes [Child 4 (PID 36961) exiting with status 36] from FD 11, PID 36961
Child with PID 36960 exited with status 0x2300
Child with PID 36959 exited with status 0x2200
Child with PID 36958 exited with status 0x2100
Child with PID 36957 exited with status 0x2000
Child with PID 36961 exited with status 0x2400
...