C 父和子同步信号故障
所以,我的任务是以这种方式同步父母和他的两个孩子: 一个子系统向父系统发送SIGUSR2信号,然后阻塞等待的父系统消息。 同步由全局标志实现,因此父级等待任何标志变为1(在子级发送SIGUSR2时发生),然后向该子级发送信号SIGUSR1,子级恢复(导致全局标志变为1) 问题在于,父节点只接收来自一个子节点的信号,然后阻塞等待第二个子节点的信号,但它们不会出现 . 有什么想法吗C 父和子同步信号故障,c,linux,synchronization,signals,C,Linux,Synchronization,Signals,所以,我的任务是以这种方式同步父母和他的两个孩子: 一个子系统向父系统发送SIGUSR2信号,然后阻塞等待的父系统消息。 同步由全局标志实现,因此父级等待任何标志变为1(在子级发送SIGUSR2时发生),然后向该子级发送信号SIGUSR1,子级恢复(导致全局标志变为1) 问题在于,父节点只接收来自一个子节点的信号,然后阻塞等待第二个子节点的信号,但它们不会出现 . 有什么想法吗 #include <stdlib.h> #include <stdio.h> #include
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/signalfd.h>
#define LPC 10
pid_t ch[2];
sig_atomic_t flag_ch[2] = {0, 0};
sig_atomic_t flag_p = 0;
int get_ind(pid_t ch_pid) {
int i;
for (i = 0; i < 2; ++i) {
if (ch_pid == ch[i])
return i;
}
return -1;
}
void usr_handler(int signo, siginfo_t* si, void* unused) {
int ch_index;
switch(signo) {
case SIGUSR2:
ch_index = get_ind(si->si_pid);
if (ch_index >= 0)
flag_ch[ch_index] = 1;
else
fprintf(stderr, "signal handled not from child pid %d\n", si->si_pid);
break;
case SIGUSR1:
flag_p = 1;
break;
}
}
void set_usr_handler(void) {
struct sigaction sa;
sa.sa_sigaction = usr_handler;
sa.sa_flags = SA_SIGINFO;
sa.sa_restorer = NULL;
sigemptyset(&sa.sa_mask);
if (0 != sigaction(SIGUSR1, &sa, NULL))
abort_prg("signal [SIGUSR1] error");
if (0 != sigaction(SIGUSR2, &sa, NULL))
abort_prg("signal [SIGUSR2] error");
}
void child_proc(void) {
int i;
for (i = 0; i < LPC; ++i) {
if (0 != kill(getppid(), SIGUSR2))
exit(1);
while (0 == flag_p) { };
flag_p = 0;
}
}
int wait_child(void) {
while (0 == flag_ch[0] && 0 == flag_ch[1]) { };
if (1 == flag_ch[0]) {
flag_ch[0] = 0;
return ch[0];
}
flag_ch[1] = 0;
return ch[1];
}
void parent_proc(void) {
int i;
pid_t ch_pid;
for (i = 0; i < LPC * 2; ++i) {
ch_pid = wait_child();
printf("Parent: Received from pid [%d]\n", ch_pid);
if (0 != kill(ch_pid, SIGUSR1))
exit(1);
}
}
int main(int argc, char* argv[]) {
set_usr_handler();
int i;
for (i = 0; i < 2; ++i) {
pid_t child = fork();
if (0 > child)
exit(1);
if (0 == child) {
child_proc();
return 0;
}
ch[i] = child;
}
parent_proc();
return 0;
}
#包括
#包括
#包括
#包括
#包括
#定义LPC10
pid_t ch[2];
sig_原子标志[2]={0,0};
sig_原子标志p=0;
int get\U ind(pid\U t ch\U pid){
int i;
对于(i=0;i<2;++i){
if(ch_pid==ch[i])
返回i;
}
返回-1;
}
void usr_处理程序(int signo、siginfo_t*si、void*未使用){
int CHU指数;
开关(信号){
案例信号2:
ch_索引=获取索引(si->si_pid);
如果(Chu索引>=0)
flag_ch[ch_index]=1;
其他的
fprintf(标准,“非从子pid%d\n处理的信号”,si->si_pid);
打破
案例SIGUSR1:
标志p=1;
打破
}
}
void set\u usr\u处理程序(void){
struct-sigaction-sa;
sa.sa_sigaction=usr_handler;
sa.sa_flags=sa_SIGINFO;
sa.sa_restorer=NULL;
sigemptyset(和sa.sa_面具);
如果(0!=sigaction(SIGUSR1,&sa,NULL))
中止prg(“信号[SIGUSR1]错误”);
如果(0!=sigaction(SIGUSR2,&sa,NULL))
中止prg(“信号[SIGUSR2]错误”);
}
无效子进程(无效){
int i;
对于(i=0;i子级)
出口(1);
if(0==子级){
child_proc();
返回0;
}
ch[i]=儿童;
}
父进程();
返回0;
}
我猜在一些全局变量声明中缺少了volatile
。例如,flag\u p
不是volatile
意味着循环
while (flag_p == 0) { }
可以永远运行:GCC可能会编译它,以便只将全局变量加载到寄存器中一次,然后循环,直到该寄存器不为零(这永远不会发生)
保守的近似方法是,您应该将从信号处理程序读取或写入的所有可变变量设置为volatile
编辑:我能想到的另一个问题来源是信号不是累积的:要么父进程没有SIGUSR2挂起,要么它有一个。据我所知,如果两个子进程同时将其发送到父进程,那么可能只会发送一个
编辑:我认为一个“更好”的解决方案(更灵活、更便携)应该是:根本不使用信号,而是使用管道。在父级和每个子级之间制作一个管道,完成后子级在管道上发送一个字符“X”。父级使用select()等待;或者,如果它只想等待两个子级都准备好,它可以从一个管道读取“X”字符,然后从另一个管道读取,在两种情况下都会阻塞(顺序无关紧要)。您是否有意在(0==flag_p){}时写入@AnishRam否,子对象在父对象中获取的值是子对象pid。'while(0==flag_p){};'阻止子项,直到父项的信号解除,但标志\u p未相互连接。每个进程都有自己的标志,这就是为什么我使用父进程发送给子进程的信号SIGUSR1来更改标志值的原因。谢谢您的回复。我不明白的是,当两个孩子同时向父母发送信号时。您确定处理程序将执行一次吗?如果是这样,这个问题的解决方案是什么?事实上,我添加了“volatile”,但它对我没有帮助