2013-12-11 3 views
0

Я написал программу, в которой родительский процесс выдает 5 (лотерейных) номеров, полученных из списка параметров. Затем дочерний процесс генерирует 5 случайных чисел, и если одно из этих чисел равно параметрам, оно отправляет сигнал SIGUSR1, иначе SIGUSR2 в родительский процесс. Если я не использую сигналы, просто просто напечатайте ответы от ребенка, код работает нормально. Но с сигналами родительский процесс запускается дважды или, по крайней мере, его содержимое распечатывается дважды. Не могли бы вы объяснить мне такое поведение? Заранее спасибо!Родительский процесс запускается дважды после получения сигнала

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

void handler(int signumber){ 
     printf("The child got a hit, my pid: %i\n", getpid()); 
} 

void handler2(int signumber){ 
     printf("The child had no hit!\n"); 
} 

int main(int argc, char* argv[]) 
{ 
    signal(SIGUSR1,handler); 
    signal(SIGUSR2,handler2); 

    int status, child; 
    int num1 = atoi(argv[1]); 
    int num2 = atoi(argv[2]); 
    int num3 = atoi(argv[3]); 
    int num4 = atoi(argv[4]); 
    int num5 = atoi(argv[5]); 

    if (num1<0 || num1>45 || num2<0 || num2>45 || num3<0 || num3>45 || num4<0 || num4>45 || num5<0 || num5>45){ 
     perror("We need 5 numbers in range of 0 and 45"); 
     exit(1); 
    } 

    child = fork(); 

    if(child>0){ //parent 
     printf("The numbers: %i, %i, %i, %i, %i. my pid: %i \n", num1,num2,num3,num4,num5,getpid()); 
    } else{ 
     int rnd,i,isAnyHit; 
     isAnyHit = 0; 
     srand(time(NULL) * (getpid())); 
     for (i=0;i<5;i++){ 
      rnd = ((rand()%45)+1); 
      if (rnd == num1 || rnd == num2 || rnd == num3 || rnd == num4 || rnd == num5){ 
       kill(getppid(),SIGUSR1); 
       isAnyHit++; 
      } 
     } 
     if (isAnyHit == 0) 
      kill(getppid(),SIGUSR2); 
    } 
    return 0; 
} 
+1

Что произойдет, если будет проведено более одного номера? Похоже, вы отправите SIGUSR1 потенциально 5 раз, если все 5 номеров совпадают правильно? – Trenin

+0

Это поможет, если вы сообщите нам, какое сообщение дублируется. Кроме того, нам будет легче читать код, если вы переводите сообщения на английский (какой язык венгерский?). Странно, что у вас нет родителя, ожидающего ребенка, поэтому, когда вы дойдете до убийства (getppid(), ...) у ребенка, скорее всего, ваш родитель уже вышел, ваш процесс был унаследован по init-процессу, и вы отправляете сигналы init (надеюсь, вы не делаете это как root!) –

+0

Возможно, что printf родителя прерывается сигналом, а два параллельных printfs путают некоторые структуры данных. Если вы замените 'printf (« Szülő: A lottó számok:% i,% i,% i,% i,% i. Pid számom:% i \ n ", num1, num2, num3, num4, num5, getpid ()); 'с' pause(); ', все работает? В общем случае обработчики сигналов C не должны делать ничего больше, чем изменять изменчивую переменную. –

ответ

0

Я внес некоторые изменения в код, и, похоже, он работает для меня.

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


void handler(int signumber){  
    printf("Got signal %d at %i\n", signumber, getpid());  
}  

int main(int argc, char* argv[])  
{  
    signal(SIGUSR1,handler);  
    signal(SIGUSR2,handler);  

    int status, child;  
    int num1 = atoi(argv[1]);  
    int num2 = atoi(argv[2]);  
    int num3 = atoi(argv[3]);  
    int num4 = atoi(argv[4]);  
    int num5 = atoi(argv[5]);  

    if (num1<0 || num1>45 || num2<0 || num2>45 || num3<0 || num3>45 || num4<0 || num4>45 || num5<0 || num5>45){  
    perror("Invalid numbers\n");  
    exit(1);  
    }  

    child = fork();  

    if(child>0){ //szülő  
    printf("In the parent - child pid is %i, parent pid is %i\n", child, getpid());  
    sleep(1000);  
    } else{  
    printf("In the child - child pid is %i, parent pid is %i\n", getpid(), getppid());  
    int rnd,i,isAnyHit;  
    isAnyHit = 0;  
    srand(time(NULL) * (getpid()));  
    for (i=0;i<5;i++){  
     rnd = ((rand()%45)+1);  
     printf("Checking %i against numbers\n", rnd);  
     if (rnd == num1 || rnd == num2 || rnd == num3 || rnd == num4 || rnd == num5)){  
     printf("Matched %i\n", rnd);  
     kill(getppid(),SIGUSR1);  
     isAnyHit++;  
     }  
    }  
    if (isAnyHit == 0)  
     kill(getppid(),SIGUSR2);  
    }  

    printf("PID %i is ending\n", getpid());  
    return 0;  
} 

После выхода:

$ ./a.out 1 2 3 4 5 
In the parent - child pid is 20401, parent pid is 20400 
In the child - child pid is 20401, parent pid is 20400 
Checking 6 against numbers 
Checking 18 against numbers 
Checking 15 against numbers 
Checking 42 against numbers 
Checking 4 against numbers 
Matched 4 
PID 20401 is ending 
Got signal 10 at 20400 
PID 20400 is ending 

Но если 2 номера матча:

$ ./a.out 1 2 3 4 5 
In the parent - child pid is 20493, parent pid is 20492 
In the child - child pid is 20493, parent pid is 20492 
Checking 2 against numbers 
Matched 2 
Checking 5 against numbers 
Matched 5 
Checking 13 against numbers 
Got signal 10 at 20492 
Checking 36 against numbers 
Checking 19 against numbers 
Got signal 10 at 20492 
PID 20493 is ending 
PID 20492 is ending 

Я получаю 2 SIGUSR1 (10).

+0

В вашем коде есть проблема, что спящий сигнал прерывается сигналом, поэтому родительский процесс будет: a) спящий полные 1000 секунд, если нет совпадения, b) выйти после первого совпадения. Вместо сна лучше используйте что-то вроде 'int rc; while (wait (& rc) == - 1); 'ждать, пока ребенок выйдет и обработает прерывания до ожидания, перезапустив syscall. –

+0

К сожалению. Предполагается, что родитель должен получить хотя бы SIGUSR2, если нет совпадения, поэтому забудьте про спать в течение 1000 секунд. –

+0

Да, в этом случае сон не имеет значения. Я просто добавил его, потому что, когда я тестировал, родитель умирал, прежде чем получать какие-либо сигналы. Я забыл, что это были секунды, и думал, что это миллисекунды, поэтому я использовал 1000. – Trenin

Смежные вопросы