пример сигнала прерывания

#c #unix #signals #kill

#c #unix #сигналы #уничтожить

Вопрос:

Я пытаюсь использовать этот пример, который я взял из:http://www.cs.cf.ac.uk/Dave/C/node24.html:

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void sighup(); /* routines child will call upon sigtrap */
void sigint();
void sigquit();

main() { 
 int pid;

 /* get child process */

 if ((pid = fork()) < 0) {
    perror("fork");
    exit(1);
 }

if (pid == 0) { /* child */
   printf("nI am the new child!nn");
       signal(SIGHUP,sighup); /* set function calls */
       signal(SIGINT,sigint);
       signal(SIGQUIT, sigquit);
       printf("nChild going to loop...nn");
      for(;;); /* loop for ever */
 }
else /* parent */
 {  /* pid hold id of child */
   printf("nPARENT: sending SIGHUPnn");
   kill(pid,SIGHUP);
   sleep(3); /* pause for 3 secs */
   printf("nPARENT: sending SIGINTnn");
   kill(pid,SIGINT);
   sleep(3); /* pause for 3 secs */
   printf("nPARENT: sending SIGQUITnn");
   kill(pid,SIGQUIT);
   sleep(3);
 }
}

void sighup() {
   signal(SIGHUP,sighup); /* reset signal */
   printf("CHILD: I have received a SIGHUPn");
}

void sigint() {
    signal(SIGINT,sigint); /* reset signal */
    printf("CHILD: I have received a SIGINTn");
}

void sigquit() {
  printf("My DADDY has Killed me!!!n");
  exit(0);
}
  

Но я не вижу никаких выходных данных от дочернего процесса.

Это ожидаемое поведение? Если да, то почему?

Большое вам спасибо!

Ответ №1:

В вашем коде есть серьезное условие гонки. Вы не гарантируете, что дочерний сервер завершил вызов signal до того, как родительский сервер отправит сигналы. Вам либо нужно использовать какой-то примитив синхронизации, чтобы заставить родительский элемент ждать, пока дочерний элемент установит обработчики, либо вам нужно установить обработчики сигналов перед разветвлением, чтобы дочерний элемент унаследовал их.

Вот самый простой я знаю способ синхронизации процессов, подобных этому:

  1. Перед разветвлением вызовите pipe(p) для создания канала.
  2. fork() .
  3. В родительском, close(p[1]); (конец записи) и read(p[0], amp;dummy, 1);
  4. В дочернем, close(p[0]); и close(p[1]); после установки обработчиков сигналов.
  5. Когда родительский сервер возвращается из read , вы можете быть уверены, что дочерний сервер настроил свои обработчики сигналов. На этом этапе вы также можете close(p[0]); использовать родительский файл.

Правка 2: Возможно, лучший и более простой подход:

  1. Перед разветвлением вызовите sigprocmask , чтобы заблокировать все сигналы и сохранить старую маску сигнала.
  2. В родительском файле вызовите sigprocmask снова сразу после разветвления, чтобы восстановить исходную маску сигнала.
  3. В дочернем элементе вызовите sigprocmask сразу после установки обработчиков сигналов, чтобы восстановить исходную маску сигнала.

Ответ №2:

Вы должны использовать getpid() вместо pid().

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

1. OP, упомянутый вывод из дочернего процесса () отсутствует. getpid() выдаст только идентификатор процесса. решит ли это проблему?