该程序旨在永久发出交易信号。 SIGUSR1
由父级捕获,SIGUSR2
由子级捕获。当他们捕捉到自己的信号时,他们只玩旗帜。我首先让父进程运行,也就是说,首先父进程发送信号。子进程通过 pause()
等待其进程,直到它动态运行其捕获器。我以为我应用了一个简单的同步,但似乎没有。但是,如果我在 usleep(1000)
中发表评论,则代码可以正常工作。喜欢
initial value, flag = -99
child process, flag = 0
parent process, flag = 1
child process, flag = 0
parent process, flag = 1
child process, flag = 0
.
.
.
child process, flag = 0
parent process, flag = 1
child process, flag = 0
parent process, flag = 1
child process, flag = 0
.
.
.
但是如果不 sleep ,我就无法得到我想要的东西。我想不眠不休地实现我的愿望。错误的输出是,
initial value, flag = -99
parent process, flag = -99
waits forever..................
如何才能按预期运行?然而,这种行为的原因是什么?顺便说一句,我必须仅使用没有信号量、互斥体等的信号来应用同步。所有 posix 信号功能,除了 sleep 、nanosleep 或暂停和忙等待之外,都可以使用,如 sigaction、sigsuspend 等。
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
volatile sig_atomic_t flag = -99; // child = 0, parent = 1;
void catcher(int sig) {
switch (sig) {
case SIGUSR1 : flag = 1; break;
case SIGUSR2 : flag = 0; break;
}
}
int safeBlockParent(int signum) {
sigset_t maskall, maskmost, maskold;
sigfillset(&maskall);
sigfillset(&maskmost);
sigdelset(&maskmost, signum);
sigprocmask(SIG_SETMASK, &maskall, &maskold);
if (flag == 0)
sigsuspend(&maskmost);
sigprocmask(SIG_SETMASK, &maskold, NULL);
}
int safeBlockChild(int signum) {
sigset_t maskall, maskmost, maskold;
sigfillset(&maskall);
sigfillset(&maskmost);
sigdelset(&maskmost, signum);
sigprocmask(SIG_SETMASK, &maskall, &maskold);
if (flag == 1)
sigsuspend(&maskmost);
sigprocmask(SIG_SETMASK, &maskold, NULL);
}
void ChildProcess() {
while(1) {
safeBlockChild(SIGUSR2);
fprintf(stderr, "child process, flag = %d\n", flag);
kill( getppid(), SIGUSR1 );
}
}
void ParentProcess(pid_t childPid) {
flag = 1;
while(1) {
//usleep(1000);
fprintf(stderr, "parent process, flag = %d\n", flag);
kill( childPid, SIGUSR2 );
safeBlockParent(SIGUSR1);
}
}
int main() {
pid_t pid;
struct sigaction sact = { 0 };
fprintf(stderr, "initial value, flag = %d\n", flag);
sigemptyset( &sact.sa_mask );
sact.sa_flags = 0;
sact.sa_handler = catcher;
if (sigaction (SIGUSR1, &sact, NULL) < 0) {
perror("sigaction sigusr1 error");
exit(1);
}
if (sigaction (SIGUSR2, &sact, NULL) < 0) {
perror("sigaction sigusr2 error");
exit(2);
}
pid = fork();
if (pid < 0) { perror("fork problem"); exit(3); }
if (pid == 0) {
//kill(getppid(), SIGUSR1);
ChildProcess();
}
else {
ParentProcess(pid);
//wait(NULL);
}
return 0;
}
代码有时会卡住,有时会运行。
最佳答案
您有两个竞争条件:
- 父进程可以在子进程有机会为
SIGUSR2
注册信号处理程序之前发送信号。 - 一个进程可以在另一个进程处于
暂停
之外时发送信号。
后者可能会在第一次时发生,此时子进程尚未达到暂停
,但父进程已发送SIGUSR2
。这会导致您看到的效果。
关于c - 与信号的简单同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49619309/