Потерянные сигналы от дочернего элемента к родительскому

#c #linux

#c #linux

Вопрос:

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

Как я должен это закодировать?

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

int ended = 0;

void handler(int sig){
    ended  ;
}

int main(int argc, char **argv){
    int i;
    pid_t pid, ppid;

    if (signal(SIGUSR1, handler) < 0) {
        fprintf(stderr, "signal failed.n");
        exit (-1);
    }

    ppid = getpid();

    for (i = 0; i < 50; i  ){
        if ((pid = fork()) < 0){
            fprintf(stderr, "fork failed.n");
            exit(-1);
        }
        if (pid == 0){  
            kill(ppid, SIGUSR1);
            exit(0);
        }       
    }

    while (wait(NULL) > 0);

    printf("ended = %dn", ended);

    return 0;
} 
  

Выходные данные для этой программы иногда составляют 47, другие 39… но никогда не 50

Комментарии:

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

2. В дополнение к комментарию Занга, вы не можете записывать в статический int внутри обработчика сигнала, вызываемого через kill , это неопределенное поведение. См. en.cppreference.com/w/c/program/signal .

Ответ №1:

Проблема здесь в том, что сигнал действует как аппаратное прерывание, где вашей функцией обработчика будет ISR (процедура обслуживания прерываний). Затем, если несколько сигналов одного и того же значения происходят «одновременно», ядро Linux обрабатывает их только как один сигнал. Сигнал не предназначен для использования таким образом. Сигнал должен использоваться для информирования о состоянии процесса другому. Для обеспечения связи между процессами вы должны использовать механизмы IPC (межпроцессные коммуникации), такие как очередь, сокеты или каналы.

Ответ №2:

Спасибо,

Я обнаружил, что проблема может быть решена с использованием сигналов реального времени. Просто меняю SIGUSR1 на SIGRTMIN. Сигналы в реальном времени помещаются в очередь (http://man7.org/linux/man-pages/man7/signal.7.html ).

Есть ли какие-либо негативные побочные эффекты в этом решении?

Ответ №3:

это работало..

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

int ended = 0;

void handler(int sig)
{
    ended  ;
}

    int main(int argc, char **argv)
    {
        int i;
        pid_t pid, ppid;

        if (signal(SIGUSR1, handler) < 0)
        {
            fprintf(stderr, "signal failed.n");
            exit (-1);
        }

        ppid = getpid();

        for (i = 0; i < 50; i  )
        {
            if ((pid = fork()) < 0)
            {
                fprintf(stderr, "fork failed.n");
                exit(-1);
            }
            if (pid == 0)
            {
                kill(ppid, SIGUSR1);
                exit(0);
            }
        }

        while (wait(NULL) > 0);

        printf("ended = %dn", ended);

        return 0;
    }
  

Комментарии:

1. Это тот же код, просто переформатированный без причины?