如何让两个进程不断地互相发信号?

How to make two processes signalling each others continuously?

我想模拟一个游戏服务器,它应该用 parent 连续发送和接收信号。场景如下:

等等...

问题是在第一圈后停止接收或发送:

static int game_s;
void game()
{   
    printf("game\n");
    signal(SIGUSR1,game);
    sleep(1);
    kill(getppid(),SIGUSR1);
    pause();
}
void parent()
{
    printf("parent\n");
    signal(SIGUSR1,parent);
    sleep(1);
    kill(game_s,SIGUSR1);
    pause();
}
void main()
{

    game_s = fork();
    if(game_s>0)
    {       
        signal(SIGUSR1,parent);
        sleep(1);
        kill(game_s,SIGUSR1);
        pause();
    }
    else
    {
        signal(SIGUSR1,game);
        pause();
    }
}

输出如下:

game
parent

为什么停在这里?游戏服务器不应该捕获parent的信号并再次打印"game"吗...

默认情况下,从进程收到此特定信号的那一刻起,直到相关的信号处理程序已离开,才会阻止接收特定信号。

来自 man 3 signal:

void (*signal(int sig, void (*func)(int)))(int);

[...]

When a signal occurs, and func points to a function, it is implementation-defined whether the equivalent of a:

         signal(sig, SIG_DFL);

is executed or the implementation prevents some implementation-defined set of signals (at least including sig) from occurring until the current signal handling has completed.

要更改此行为,请通过 sigaction() 而不是 signal() 建立信号处理(出于可移植性原因,应该采取任何方式)。

sigaction()需要一个struct sigaction。后者的成员sa_flags应该设置SA_NODEFER

来自 Linux' man 2 sigaction:

SA_NODEFER

Do not prevent the signal from being received from within its own signal handler. This flag is meaningful only when establishing a signal handler.

POSIX words this differently:

SA_NODEFER

If set and sig is caught, sig shall not be added to the thread's signal mask on entry to the signal handler unless it is included in sa_mask. Otherwise, sig shall always be added to the thread's signal mask on entry to the signal handler.


请注意,每个信号处理程序在每次被调用时都会分配自己的堆栈,因此这种递归乒乓球迟早会出现内存不足的情况。

使用消息队列或共享内存来执行此操作。如上所述,这最终会 运行 内存不足并且会崩溃。