2016-03-25 27 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? –