我正在尝试通过在C中使用POSIX信号来实现进程间通信,尤其是我正在写乒乓球问题。所以这是我的源代码:

#define CHILD 0
#define PARENT 1

int flag[2];

void handler(int sig) {
    if (sig == SIGUSR1) {
        flag[PARENT] = 1;
    } else {
        flag[CHILD] = 1;
    }
    return;
}

void child_process() {
    while (1) {
        printf("Ping!\n");
        kill(getppid(), SIGUSR2);
        while (flag[PARENT] == 0) { }
    }
    return;
}

void parent_process(pid_t t) {
    while (1) {
        //kill(t, SIGUSR1);
        while (flag[CHILD] == 0) { }
        printf("Pong!\n");

        kill(t, SIGUSR1);
    }
    return;
}

void setup() {
    flag[CHILD] = 0;
    flag[PARENT] = 0;
    signal(SIGUSR1, handler);
    signal(SIGUSR2, handler);
}

int main(int argc, char* argv[]) {
    setup();
    pid_t t = fork();
    if (t == 0) {
        child_process();
    } else {
        parent_process(t);
    }
    return 0;
}


我的程序无法正常运行,因为有时我会收到“ Pong!”的声音。 “乒乓球!” “乒乓球!”或“ Ping!” “砰!”输出。有什么问题?

还有一个问题,我处理信号的方式正确吗?还是有更高级的方法来做到这一点?

最佳答案

(1)父母与子女不共享相同的记忆。 flag [CHILD]和flag [PARENT]将永远不会彼此了解,因为它们是不同进程中的不同副本。

(2)是的,关于信号处理的几乎所有事情都与您尝试做的事情有关。您正在尝试同步信号,因此您需要使用一种实际上将其同步的机制,例如sigsuspend

#define _POSIX_C_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

void sig_hand(int sig) {}

sigset_t saveMask, blockMask;

void child_process()
{
    int x = 0;

    while(x < 10)
    {
        if (sigsuspend(&saveMask) == -1 && errno != EINTR)
            errExit("sigsuspend");

        printf("Pong %d!\n", ++x);

        kill(getppid(), SIGUSR1);
    }

    return ;
}

void parent_process(pid_t pid)
{
    int y = 0;

    while (y < 10)
    {
        printf("Ping %d!\n", ++y);

        kill(pid, SIGUSR1);

        if (sigsuspend(&saveMask) == -1 && errno != EINTR)
            errExit("sigsuspend");
    }

    return ;
}


int main(int argc, char* argv[])
{
    //block SIGUSR1 in parent & child until ready to process it
    sigemptyset(&blockMask);
    sigaddset(&blockMask, SIGUSR1);

    if (sigprocmask(SIG_BLOCK, &blockMask, &saveMask) == -1)
        errExit("sigprocmask");

    //set up signal handler for parent & child
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = sig_hand;

    if (sigaction(SIGUSR1, &sa, NULL) == -1)
        errExit("sigaction");

    pid_t pid = fork();

    if (pid == 0)
        child_process();
    else
        parent_process(pid);

    return 0;
}

07-28 05:45