在linux c编程中的信号
我正在用3个进程编写一个系统, Judge
, Player 1
和player 2
。
我使用信号kill(playerPid,SIGUSR1)
让judge
在轮到他时唤醒一名player
,并在信号完成后用信号kill(judge,SIGHUP)
来唤醒法官。
在每个kill signal
我使用一个pause()
所以这个过程不会继续。 问题有时会发生在例如来自player
judge
的kill signal
之后,在球员pause()
之前, judge
醒来pause()
。 并且下一次judge
会唤醒这名player
他会pause
并且我的程序将会叠加,因为所有3 processes
都处于pause
状态,没有人会将其唤醒。
所以我的问题是:杀死命令后应该发生什么?
1 。 当前过程一直持续到暂停(),然后进入他发出信号的过程。 例如:
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 %dn", signo);
if(signo == SIGHUP )//fatehr gets it from son
{
signal(SIGHUP ,sigHandler);
printf("son woke up fathern");
}
else if (signo == SIGUSR1)//son gets it from father
{
signal(SIGUSR1, sigHandler);
printf("Judge waking player Bn");
}
else if (signo == SIGUSR2)//father gets it from son
{
signal(SIGUSR2, sigHandler);
printf("Judge waking player An");
}
else if (signo == SIGTERM)//son get it when father kill them
{
signal(SIGTERM, sigHandler);
printf("%d im deadn", 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 startedn");
while(boardPtr[1]!=0)//Players didnt set up their handlers
{
sleep(1);
}
printf("father initiatingn");
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 startedn", getpid());
boardPtr[1]--;//mark player A handlers are set.
pause();
while (1)
{
int r = roll(1);
printf("%d player A threw a %dn", 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 startedn", getpid());
boardPtr[1]--;//mark player A handlers are set.
pause();
while (1)
{
int r = roll(2);
printf("%d player B threw a %dn", 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;
}
用这样的东西替换每个杀/暂停对
/* 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);
}
链接地址: http://www.djcxy.com/p/50025.html