Как синхронизировать два процесса (дочерний и родительский) с сигналами в C? - PullRequest
0 голосов
/ 28 июня 2018

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

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



void trataSIGUSR1(int sigNum) {
    printf("SIGUSR1\n");
}

int main(void) {

    pid_t pid;
    struct sigaction sa;

    pid = fork();

    if (pid == 0) {
        struct sigaction sa = {0};
        sa.sa_handler = trataSIGUSR1;
        sa.sa_flags = 0;
        sigemptyset(&sa.sa_mask);
        sigaction(SIGUSR1,&sa,NULL);
        pause();
        printf("This never execute");
    } else {
        printf("I'am father: %d!\n",getppid());
        kill(0,SIGUSR1);
        pause();
    }
}

OUTPUT

I'am father: 12082!
User defined signal 1: 30

1 Ответ

0 голосов
/ 28 июня 2018

Простая подсказка - это использование pause() и kill(), т. Е. pause() - для блокировки выполнения процесса до тех пор, пока не получен какой-либо сигнал, после получения сигнала затем do_something() и kill() - для отправки сигнала SIGUSR1.

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

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ pause() возвращается только когда signal was caught и signal-catching function возвращены. В этом случае pause () возвращает -1, а errno устанавливается в EINTR.

Вот пример требуемого примера кода

//int nSIGINT = 0; /* declare variable of type volatile sigatomic_t  */
volatile sigatomic_t nSIGINT;
void trataSIGINT(int sigNum) {
    nSIGINT = 1;/* set the flag as needed */
}
int main(void ){
        int pid;
        pid=fork();/* create child process */
        if(pid==0) {    
                //signal(SIGUSR1,trataSIGINT);/* instead of signal() use sigaction  */
                struct sigaction sa = {0}; /* initialize sa or fill all its members*/
                sa.sa_handler = trataSIGINT;/* set the handler to trataSIGINT*/
                sa.sa_flags = 0;
                sigemptyset(&sa.sa_mask);
                sigaction(SIGUSR1,&sa,NULL); /* when child received SIGUSR1, trataSIGINT gets called */
                pause(); /* wait until any signal received */
                /* do_something_child() code, this you want to run only after receiving signal */

        }
        else { 
                /* do_something_parent() */
                printf("parent about to send user signal to child\n");
                kill(pid,SIGUSR1); /*send SIGUSR1 to child */
                wait(0); /* wait till child completes  */
        }
        return 0;
}

Примечание, для установки флага в trataSIGINT() при получении SIGUSR1 вместо объявления int nSIGINT = 0; объявления переменной флага как типа volatile sigatomic_t.

Из ИСО / МЭК 9899: 2011 §7.14.1.1 Функция signal

¶5 Если сигнал возникает не в результате вызова abort или raise функция, поведение не определено, если обработчик сигнала относится к любому объекту с static или продолжительности хранения потока, который не lock-free atomic object, кроме как путем присвоения значения объект объявлен как volatile sig_atomic_t или обработчик сигнала вызывает любую функцию в стандартной библиотеке, кроме abort функция _Exit, функция quick_exit или сигнальная функция с первым аргументом, равным номеру сигнала соответствующий сигналу, вызвавшему вызов обработчика. Кроме того, если такой вызов функции сигнала приводит к SIG_ERR возврат, значение errno неопределенное.252)

252) Если какой-либо сигнал генерируется асинхронным обработчиком сигнала, поведение undefined.

...