#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. Это тот же код, просто переформатированный без причины?