Обработка сигналов в C - PullRequest
       4

Обработка сигналов в C

5 голосов
/ 16 декабря 2010

Я выясняю, как работают сигналы в C. Вот один из примеров, взятых из старых экзаменов:

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

//#include <sys/types.h>

void handler1(int sig) {
 printf("Phantom");
 exit(0);
}
int main()
{
   pid_t pid1;
   signal(SIGUSR1, handler1); //installing signal handler
   if((pid1 = fork()) == 0) { //forking
       printf("Ghost");
       exit(0);
   }
   kill(pid1, SIGUSR1);
   printf("Ninja");
   return 0;
}

Пока что GCC дает мне два ответа Ghost Ninja & Ninja Phantom. Может ли он произвести Ghost Phantom Ninja или любую другую комбинацию из трех имен?

Один способ, которым я вижу, мог бы произвести 3 имени: Разветвление, запуск в Child, печать Ghost, выход (0) => в Parent, принятие / обработка сигнала и из сигнала Обработчик печати Phantom, kill child, печать Ninja Но я не уверен, что моя «теория» имеет основание.

Кроме того, kill(pid1, SIGUSR1) будет вызывать handler()?

Спасибо!

Ответы [ 4 ]

6 голосов
/ 16 декабря 2010

Давайте рассмотрим эту строку за строкой. Установите обработчик сигнала, затем форк. Ребенок печатает «Призрак» и выходит. Родитель заставляет ребенка распечатать «Призрак» и выйти. Затем родитель печатает «ниндзя».

Итак, у вас действительно есть состояние гонки. Если родитель запускает свой SIGUSR1 до того, как ребенок напечатает «Призрак», тогда вы получите Phantom Ninja или, возможно, Ninja Phantom (уничтожить блок?)

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

Теперь вполне возможно, что сигнал может быть точно по времени, чтобы попасть между printf и exit, в этом случае Ghost закончится, затем Phantom затем Ninja - или снова наоборот, я думаю.

Это действительно привередливый и чувствительный к времени ОС.

@ Все - не проверено! Не стесняйтесь мне противоречить, но мне будет интересно узнать почему, как и ОП.

1 голос
/ 16 декабря 2010

Сначала отметим строки с номерами строк следующим образом:

signal(SIGUSR1, handler1); //installing signal handler ---- 1
   if((pid1 = fork()) == 0) { //forking                ---- 2
       printf("Ghost");                                ---- 3
       exit(0);                                        ---- 4
 }
   kill(pid1, SIGUSR1);                                ---- 5
   printf("Ninja");                                    ---- 6

Теперь с приведенным выше кодом, если Ребенок выполняет сначала и если сначала выполняется 3, то дочерний элемент приостанавливается, а родительский начинает выполнение с 5. Это выдает GhostPhantomNinja

Однако определенный порядок не может быть определен.

0 голосов
/ 16 декабря 2010
//#include <sys/types.h>
#include<stdlib.h>
void handler1(int sig) {
 printf("Phantom\n");
 waitpid(-1,NULL,0);
 //sexit(0);
}
int main()
{
   pid_t pid1;
   signal(SIGUSR1, handler1); //installing signal handler
        printf("my pid is %d ha ha parent..\n",getpid());
   //if((pid1 = fork()) == 0) { //forking
       pid1=fork();
       if(pid1==0)//in childe processs
       {
    printf("my pid is %d ha ha child..\n",getpid());
       printf("Ghost\n");
       sleep(6);
       exit(0);
   }
   else{
  //sleep(4); 
   kill(pid1, SIGUSR1);
   sleep(3);
   printf("Ninja\n");
   return 0;
}
}
0 голосов
/ 16 декабря 2010

У вас есть два недетерминированных фактора, которые оба зависят от ОС: когда произойдет переключение контекста и когда поступит сигнал.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...