Передать значение между процессами, используя каналы в цикле - PullRequest
0 голосов
/ 07 апреля 2020

Я пытаюсь создать программу, которая разветвляется на 4 дочерних процесса. Первый дочерний элемент принимает значение, объявленное перед разветвлением, уменьшает его, а затем передает его по трубе во второй процесс. Последний увеличивает значение и передает его третьему. 3 -> 4, 4 - 1 и так далее. Программа завершится при достижении 0 и выйдет с PID ребенка, который получил это 0.

Вот что я попробовал:

volatile sig_atomic_t end = 1;

Сначала я установил обработчик сигнала:

void sighandler(int sig)
{
        (void)sig;
        end = 0;
}

Затем я назначил действие SIGUSR1:

void prepare()
{
        struct sigaction s;
        s.sa_handler = sighandler;
        s.sa_flags = 0;
        sigemptyset(&s.sa_mask);
        sigaddset(&s.sa_mask, SIGUSR1);
        sigaction(SIGUSR1, &s, NULL);
}

Это мое основное:

int main()
{

    pid_t cpid, first;
    int status;
    int COUNT = 10;
    int pipes[NPROC];
    prepare();
    for (int i = 0; i < 2; i++)
    {
            pipe(pipes + 2 * i);
    }

    for (int i = 0; i < NPROC; i++)
    {
            switch (first = fork())
            {
            case -1:
                    perror("fail");
            case 0:
                    if (i % 2 == 0)
                    {
                            while (end)
                            {
                                    dup2(pipes[i], 0);
                                    read(pipes[i], &COUNT, sizeof(COUNT));
                                    COUNT--;
                                    if (COUNT < 0)
                                            kill(getppid(), SIGUSR1);
                                    dup2(pipes[i + 1], 1);
                                    write(pipes[i + 1], &COUNT, sizeof(COUNT));
                                    for (int j = 0; j < NPROC; j++)
                                            close(pipes[j]);
                            }
                    }
                    else
                    {
                            while (end)
                            {
                                    dup2(pipes[i - 1], 0);
                                    read(pipes[i - 1], &COUNT, sizeof(COUNT));
                                    COUNT--;
                                    if (COUNT < 0)
                                            kill(getppid(), SIGUSR1);
                                    dup2(pipes[(i + 2) % NPROC], 1);
                                    write(pipes[(i + 2) % NPROC], &COUNT, sizeof(COUNT));
                                    for (int j = 0; j < NPROC; j++)
                                            close(pipes[j]);
                            }
                    }
                    exit(i);
            }
            printf("Start %d \n", first);
    }

    for (int i = 0; i < NPROC; ++i)
    {
            cpid = wait(&status);

            if (!WIFEXITED(status))
                    printf("Error in child %d\n", (int)cpid);
            else
                    printf("Finished %d\n", (int)cpid);
    }
    return EXIT_SUCCESS;
}

Идея в том, что программа работает, устанавливает обработчик сигнала. Обработчик сигнала при запуске останавливает все дочерние процессы и позволяет им выйти. Затем я форк 4 процесса. Каждый будет открывать и закрывать определенные трубки, чтобы общаться друг с другом, и в то же время каждый уменьшает значение и передает его. Когда значение достигнет 0, сигнал будет повышен, и мы получим идентификатор процесса, который отправил сигнал. Когда я запускаю программу, она запускается, а потом просто ждет бесконечно ... Чего мне не хватает?

...