2016-03-25 28 views
2

我正在用3个进程编程系统,Judge,Player 1player 2linux c程序中的信号

我用信号kill(playerPid,SIGUSR1)judge醒来就轮到他一个player, 和信号kill(judge,SIGHUP)唤醒法官后,又是完整的。

之后每个kill signal我使用pause()所以过程将不会继续。 问题有时在kill signal之后,例如从playerjudgejudge在玩家正在做他的pause()之前醒来。 和下一次judge会唤醒这个player他会pause和我的程序将堆栈,因为所有3 processes处于pause状态,没有人唤醒它们。

so so question is: kill命令后会发生什么?

。当前过程一直持续到暂停(),然后进入他发出信号的过程。 例如:

kill(judge, SIGHUP); 
    //stops here and goes to the judge.  
pause(); 

这就是有时会发生在我的代码和我卡住与pause()的所有进程。

。当前进程停止并进入他刚刚发送的进程。 例如:

kill(judge, SIGHUP); 
pause(); 
//stops here and going to the judge. 

**这是大部分的时间发生在我的代码。

在我的代码的行为的变化,有时它像1号,有时像数2

我到底做错了什么?

在接收到信号的处理函数完成运行之前,是否可以唤醒进程?

或者在进入暂停行之前,进程是否可能在kill信号后暂停?如果是的话,为什么以及如何处理?

这里是我的代码:

///////////////////////signal handlers 

void sigHandler(int signo) 
{ 
    printf("Received signal %d\n", signo); 

    if(signo == SIGHUP)//fatehr gets it from son 
    { 
     signal(SIGHUP ,sigHandler); 
     printf("son woke up father\n"); 
    } 
    else if (signo == SIGUSR1)//son gets it from father 
    { 
     signal(SIGUSR1, sigHandler); 
     printf("Judge waking player B\n"); 
    } 
    else if (signo == SIGUSR2)//father gets it from son 
    { 
     signal(SIGUSR2, sigHandler); 
     printf("Judge waking player A\n"); 
    } 
    else if (signo == SIGTERM)//son get it when father kill them 
    { 
     signal(SIGTERM, sigHandler); 

     printf("%d im dead\n", getpid()); 
     kill(getppid(), SIGUSR2); 

     exit(1); 
    } 
    else if (signo == SIGINT)//father get it to play round with ^C 
    { 
     signal(SIGINT, sigHandler); 

     printf("play round!!!!!!!!!!!!\n"); 
    } 
} 

void sigHandler2(int signo) 
{ 
    if (signo == SIGINT)//son get it to play round with ^C 
    { 
     signal(SIGINT, sigHandler2); 
    } 
} 


void wakePlayer(int player,int turn, int* boardPtr) 
{ 
    boardPtr[27] = 0; 
    while (boardPtr[27] != 1)//while player didnt finish his turn 
    { 
     if (turn==1) 
      kill(player, SIGUSR1); 
     else 
      kill(player, SIGUSR2); 
     pause(); 
    } 

} 


///////////////////////End of signal handlers 
int main(){ 

    int j = 1;; 
    int player1; 
    int player2; 
    int judge; 
    time_t t; 
    key_t key; 
    int shmid; 
    int *boardPtr; 
    judge = getpid(); 
    srand(time(NULL) *(5)); 

    shmid = createShm(&boardPtr);//creating shm 
    boardPtr[1] = 2; 


    player1 = fork();//create player 1 
    if (player1 == -1) 
    { 
     printf("error in fork"); 
     exit(1); 
    } 
    if (player1>0)//not player 1 
    { 
     player2 = fork();//create player 2 
     if (player2 == -1) 
     { 
      printf("error in fork"); 
      exit(1); 
     } 
     if (player2>0)//This is The Judge!******************************************************************************** 
     { 
      signal(SIGHUP, sigHandler);//signal from player after he did his turn 
      signal(SIGINT, sigHandler);//catch the ^c to make the next turn 
      printf("father started\n"); 
      while(boardPtr[1]!=0)//Players didnt set up their handlers 
      { 
       sleep(1);  
      } 
      printf("father initiating\n"); 
      initiation(boardPtr, player1, player2);//create the board and choose a player to start 

      printBoard(boardPtr, 0);//print the current board. 

      while (checkWin(boardPtr) == 0)//while no one won. 
      { 
       if (boardPtr[26] == 1)//if it is player "b" turn. 
        wakePlayer(player1,1, boardPtr); 
       else //if it is player "a" turn.  
        wakePlayer(player2,2, boardPtr); 

       //pause(); 
       printBoard(boardPtr, j);//print the current board. 
       boardPtr[26] = (boardPtr[26] * 2) % 3;//change turns 
       j++; 
      } 

      printf("game finished!\n"); 
      killItWithFire(player1, player2, shmid, &boardPtr);//cleaning up after match. 
      printf("Judge is suiciding, goodbye!\n"); 
      exit(1); 
     } 
     else if (player2 == 0)//this is player 2!****************************************************************************** 
     { 
      signal(SIGUSR2, sigHandler);//signal from judge to make a turn 
      signal(SIGTERM, sigHandler);//signal from judge to terminate 
      signal(SIGINT, sigHandler2);//get the ^c and pause. 
      printf("%d player A started\n", getpid()); 

      boardPtr[1]--;//mark player A handlers are set. 
      pause(); 
      while (1) 
      { 
       int r = roll(1); 
       printf("%d player A threw a %d\n", getpid(), r); 
       if (boardPtr[22] == 0)//checking if it is an initation round 
       { 
        boardPtr[21] = r; 
       } 
       else 
       { 
        turn(2, r, boardPtr);//makes a turn 
       } 
       boardPtr[27] = 1;//mark that i finished my turn. 
       kill(judge, SIGHUP);//signal to judge after turn. 
       pause(); 



      } 

     } 
    } 
    else//this is player 1!********************************************************************************************** 
    { 

     signal(SIGUSR1, sigHandler);//signal from judge to make a turn 
     signal(SIGTERM, sigHandler);//signal from judge to terminate 
     signal(SIGINT, sigHandler2);//signal to pause when player gets a ctrl C 
     printf("%d player B started\n", getpid()); 

     boardPtr[1]--;//mark player A handlers are set. 
     pause(); 
     while (1) 
     {   
      int r = roll(2); 
      printf("%d player B threw a %d\n", getpid(), r); 
      if (boardPtr[22] == 0)//flag to check if it is an initiation round. 
      { 
       boardPtr[20] = r; 
      } 
      else 
      { 
       turn(1, r, boardPtr);//player b makes a turn 
      } 
      boardPtr[27] = 1;//marks that player B finished his turn. 
      kill(judge, SIGHUP);//signal to judge after turn. 
      pause(); 

     } 

    } 
    return 0; 
} 

回答

0

替换每个杀/暂停对像这样的东西

/* These flags are set in the interrupt handler, therefore we should 
    declare them volatile, so that the compiler can anticipate that 
    they can be changed outside the normal program flow */ 
volatile int sigusr1_flag, sigusr2_flag; 

void sighandler(int signo) { 
    if(signo == SIGUSR1) 
    sigusr1_flag = 1; 
    if(signo == SIGUSR2) 
    sigusr2_flag = 1; 
} 

void kill_and_wait(pid_t pid, int signaltosend, int signaltowait, volatile int *flag) { 
    sigset_t mask, savemask; 
    /* Create a signal set with only one element */ 
    sigemptyset(&mask); 
    sigaddset(&mask, signaltowait); 
    /* Block the signal that we are expecting back from the other process, 
    so if it arrives right after the kill(), it will be put "on hold", 
    and delivered first when it's unblocked. The active signal set is 
    saved to savemask, we'll use it later to temporarily unblock the 
    signal that we are expecting. */ 
    sigprocmask(SIG_BLOCK, &mask, &savemask); 
    /* Clear the flag that would be set when the response signal has arrived */ 
    *flag = 0; 
    /* Now we can safely send our signal. */ 
    kill(pid, signaltosend); 
    /* Repeat until the flag is set in the interrupt handler. We do this 
    because some other signal could arrive here that we would otherwise 
    ignore, but it wakes up our process early. */ 
    while(!*flag) { 
    /* It sets the mask of blocked signals temporarily to savemask, which 
     was the state when we entered ths funcion, effectively unblocking 
     signaltowait, then waits for any signal to arrive. */ 
    sigsuspend(&savemask); 
    } 
    /* restore the original signal mask */ 
    sigprocmask(SIG_UNBLOCK, &mask, NULL); 
} 
+0

可以请你解释一下什么是所有这些功能,并且击杀后,预计什么命令?继续直到暂停,或者直接进入发信过程。 –

+0

感谢您的意见。所以基本上你对你的解决方案所说的是,在我的kill命令和暂停之间,有一个信号会让我的进程在他暂停之前睡眠? –

+0

什么是signaltowait?我应该传递什么信号给那个arg? –