父进程在接收信号后运行两次

时间:2013-12-11 18:40:32

标签: c operating-system signals fork

我编写了一个程序,其中父进程打印出从参数列表中收到的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 个答案:

答案 0 :(得分: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)。