我正在尝试通过在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;
}