【发布时间】:2016-07-13 01:27:25
【问题描述】:
我正在编写一个具有 3 个进程的系统,Judge、Player 1 和 player 2。
我使用信号kill(playerPid,SIGUSR1) 让judge 在轮到他时唤醒player,
以及一个信号kill(judge,SIGHUP)在转弯完成后唤醒裁判。
在每个kill signal 之后,我使用pause(),因此该过程不会继续。
有时问题出在kill signal 之后,例如从player 到judge,judge 在玩家执行他的pause() 之前唤醒。
下一次judge 将唤醒这个player 他将pause 和我的程序将堆栈因为所有3 processes 都处于pause 状态没有人唤醒他们。
所以我的问题是: kill 命令之后应该发生什么?
1。当前进程一直持续到 pause() 为止,然后转到他发出信号的进程。 例如:
kill(judge, SIGHUP);
//stops here and goes to the judge.
pause();
这是我的代码中有时会发生的情况,我在 pause() 上的所有进程都卡住了。
2。当前进程停止并转到他刚刚发出信号的进程。 例如:
kill(judge, SIGHUP);
pause();
//stops here and going to the judge.
**这是我的代码中大部分时间发生的事情。
在我的代码中,行为发生了变化,有时像数字 1,有时像数字 2。
我做错了什么?
进程是否有可能在收到信号的处理函数完成运行之前唤醒?
或者进程是否有可能在终止信号之后暂停,然后再到达暂停行?如果是这样,为什么以及如何处理?
这是我的代码:
///////////////////////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;
}
【问题讨论】: