1

Тема: синхронізація батьківського та дочірніх процесів.

Привіт, я пишу програму, в якій батьківський і дочірній процеси синхронізують свої дії з сигналами.
Отже, в результаті мені потрібен повторний цикл:
1) Батьківський процес повинен надіслати сигнал SIGUSR1 групі дочірніх процесів.
2) Після отримання сигналу від батьківського процесу дочірні процеси повинні надіслати сигнал SIGUSR2 батьківському.
3) Після отримання сигналів від **всіх** дочірніх процесів батьківський процес повинен спати на 1 с. Але якщо батьківський процес отримує сигнал SIGTERM від дочірнього, батьківський має надіслати SIGTERM всім дочірнім процесам, і вони повинні припинити роботу.

Я вже написала, як створити групу дочірніх процесів і надіслати їм сигнал SIGUSR1. Але я не знаю, як надіслати сигнал SIGUSR2 від дочірніх процесів до батьківського процесу та перевірити, чи всі дочірні процеси надіслали сигнал і чи надіслані сигнали містять сигнал SIGTERM.
Будь ласка, допоможи мені!

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

static volatile sig_atomic_t got_signal;

void sig_child(int signo){
    printf("Signal caught.");
}

void handler(int sig)
{
    printf("caught signal: %d\n", getpid());
    got_signal = 1;
    signal(SIGUSR2, sig_child);
    printf("sent signal: %d\n", getpid());
    kill(getppid(), SIGUSR2);
}

int main() {

    pid_t child;
    pid_t children[3];
    int status;
    int i = 0;

    signal(SIGUSR1, handler);

    for(; i < 3; i++) {
        switch(child = fork()) {
            case -1:
                perror("could not create child: ");
                break;
            case 0:
                printf("child: %d\n", getpid());
                while (!got_signal);
                _exit(0);
            default:
                children[i] = child;
                /*put all children in process group of eldest child*/
                setpgid(child, children[0]);
        }
    }

    sleep(1);

    /* send signal to all child by sending signal to process group of eldest child */
    kill(-children[0], SIGUSR1);

    int n = 0;
    while(n < 3) {
        waitpid(children[n], &status, 0);
        n++;
    }

    exit(0);
}
Подякували: leofun011

2

Re: синхронізація батьківського та дочірніх процесів.

Для початку раджу чітко поділити код на батьківську і дочірню частини, бо зараз ви явно плутаєтеся.

signal(SIGUSR1, handler);

має виконуватися в дочірніх процесах після fork, але ж не в батьківському. Просто винесіть все, що стосується дочірнього процесу, в інший файл (або хоча б униз), додайте функцію child_main і в гілці switch викликайте її.

Далі - щоб отримати інформацію про PID процеса, що надіслав сигнал, вам треба викликати не signal, а sigaction - це дещо складніша функція.

Ну і як відстежувати: у вас є масив children, створіть такий самий з булевими значеннями. Коли отримуєте сигнал - виставляйте true, якщо всі true - значить, ви отримали сигнали від усіх.
А, і ще: ID групи - це ID не старшого нащадка, а батька. Тобто треба

kill(-getpid(), SIGUSR1);

робити, або в циклі по children.

Подякували: leofun011