我正在尝试使用信号在父进程和子进程之间传递,但是在打印前2个语句之后 例如,在我的节目中显示:
儿童4225:跑步,父母是4224
父母4224:告诉孩子进程4225开始
它永远陷入困境!我不知道我在哪里出错...
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
void p_sig_usr(int signo){
if(signo == SIGUSR1){
printf("*** Parent SIGUSR1 handler - Received 'task started' signal from child ***\n");
}
if(signo == SIGUSR2){
printf("*** Parent SIGUSR2 handler - Received 'task completed' signal from child ***\n");
}
else
printf("unexpected signal received");
return;
}
void c_sig_usr(int signo){
if(signo == SIGUSR1){
printf("*** Child SIGUSR1 handler - Received 'task start' signal from parent ***\n");
}
if(signo == SIGUSR2){
printf("*** Child SIGUSR2 handler - Received 'task complete verification' signal from parent ***\n");
}
else
printf("unexpected signal received");
return;
}
int main(void)
{
pid_t child_pid, parent_pid;
parent_pid = getpid();
struct sigaction p_sig;
sigemptyset(&p_sig.sa_mask);
p_sig.sa_flags = 0;
p_sig.sa_handler = p_sig_usr;
child_pid = fork();
if ( child_pid == -1){
perror("failed to fork a new process");
return 1;
}
if (child_pid == 0){
struct sigaction c_sig;
sigset_t c_myset;
sigemptyset(&c_sig.sa_mask);
c_sig.sa_flags = 0;
c_sig.sa_handler = c_sig_usr;
child_pid = getpid();
printf("CHILD %d: Running, parent is %d\n",child_pid, parent_pid);
sigfillset(&c_myset);
sigdelset(&c_myset, SIGUSR1);
sigsuspend(&c_myset);//suspend until get SIGUSR1
printf("CHILD: Telling parent that I'm starting task.\n");
sleep(3);
kill(parent_pid, SIGUSR1);
printf("CHILD: Performing task\n");
sigfillset(&c_myset);
sigdelset(&c_myset, SIGUSR2);
sigsuspend(&c_myset);//suspend and wait for SIGUSR2
printf("CHILD: Telling parent that work is done.\n");
kill(parent_pid, SIGUSR2);
printf("CHILD %d: Finished\n", child_pid);
}
else{
struct sigaction p_sig;
sigset_t p_myset;
sigemptyset(&p_myset);
sleep(3);//parent now sleeping to let child set up handlers
printf("PARENT %d: Telling the Child Process %d to start\n", parent_pid, child_pid);
kill(child_pid, SIGUSR1);
sigfillset(&p_myset);
sigdelset(&p_myset, SIGUSR1);
sigsuspend(&p_myset);//suspend until get SIGUSR1
sleep(3);
kill(child_pid,SIGUSR2);
printf("PARENT: Told child to notify of task completion.\n");
sigfillset(&p_myset);
sigdelset(&p_myset, SIGUSR2);//suspend until get SIGUSR2
printf("PARENT %d: Finished.", parent_pid);
}
return 0;
}
提前感谢您的帮助!
答案 0 :(得分:1)
我只是提到这些功能的文档 - 我没有使用它们的经验。
sigfillset()
似乎要将process signal mask加载到sigset_t
。这意味着您的sigset_t
将包含您的流程当前阻止的信号集。我假设默认情况下没有被阻止,因此该集合将为空。
您可能希望通过打印出该组的内容来测试它,或者只是在调试器中查看它。
现在从文档中我了解sigdelset(&p_myset, SIGUSR1)
将会做什么从您刚刚填充的集合中移除信号SIGUSR1
。假设这个集合已经是空的,所以这个调用不太可能做任何事情。再次,通过在调试器中查看它来验证。
所以现在sigsuspend()
要做的是用你的新掩码替换你的进程信号掩码,假设与默认掩码没有任何不同(再次,在调试器中检查< /强>)。然后在子端将等待进程收到SIGUSR1
并通过信号处理程序处理它。因此,您的孩子将处理SIGUSR1
,但这只是因为这是默认行为。
您的示例代码似乎没有安装任何信号处理程序。我想你必须调用sigaction()
函数来做到这一点。因此,默认信号处理程序很可能会运行以处理SIGUSR1
。
根据this page,SIGUSR1
的默认信号处理是
(i)......异常终止该过程。该过程终止于_exit()的所有后果,除了wait()和waitpid()可用的状态指示指定信号的异常终止。
所以我猜父母做kill(child_pid, SIGUSR1)
时孩子就死了。这意味着孩子不在身边向父母发出信号。
这主要是我的猜测。我建议您学习如何使用gdb
或其他一些调试器,这样您就可以设置一些断点并逐步了解程序实际执行的操作。
答案 1 :(得分:0)
在父母和孩子之间定义sigaction
后,您忘了拨打struct sigaction
。另外,请注意在父进程中重新定义struct sigaction p_sig
。
所以,我想如果你把你的程序改成下面列出的那样,它应该可以工作。
--- foo.c 2014-06-16 16:37:10.918932118 -0300
+++ bar.c 2014-06-16 16:37:48.710228467 -0300
@@ -36,10 +36,6 @@
{
pid_t child_pid, parent_pid;
parent_pid = getpid();
- struct sigaction p_sig;
- sigemptyset(&p_sig.sa_mask);
- p_sig.sa_flags = 0;
- p_sig.sa_handler = p_sig_usr;
child_pid = fork();
if ( child_pid == -1){
perror("failed to fork a new process");
@@ -51,6 +47,7 @@
sigemptyset(&c_sig.sa_mask);
c_sig.sa_flags = 0;
c_sig.sa_handler = c_sig_usr;
+ sigaction(SIGUSR1, &c_sig, NULL);
child_pid = getpid();
printf("CHILD %d: Running, parent is %d\n",child_pid, parent_pid);
sigfillset(&c_myset);
@@ -69,6 +66,10 @@
}
else{
struct sigaction p_sig;
+ sigemptyset(&p_sig.sa_mask);
+ p_sig.sa_flags = 0;
+ p_sig.sa_handler = p_sig_usr;
+ sigaction(SIGUSR1, &p_sig, NULL);
sigset_t p_myset;
sigemptyset(&p_myset);
sleep(3);//parent now sleeping to let child set up handlers