这个程序的目标是fork和让孩子睡觉,而父循环无限地等待中断。当我点击^ C时,它会调用void parent
函数。但是,此部分有效,来自kill ( pid, SIGALRM )
的消息无效。我检查了pid
是孩子的正确进程ID。
我已经搜索了一段时间,但我还没找到我做错了什么。我之前使用kill ( pid, SIGALRM )
从子进程到父进程,但我无法弄清楚为什么这不起作用..
#include <signal.h>
#include <unistd.h>
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
int pid;
void parent ( int sig )
{
kill ( pid, SIGALRM );
cout << "I'm a parent " << getpid() << " My child is " << pid << endl;
}
void child ( int sig )
{
cout << "I am " << getpid() << "my parent is " << getppid()<< endl;
cout << "Use ctrl+backslash to actually end the program" << endl;
}
int main()
{
pid = fork();
if(pid == 0)
{ //Child process
cout << "Child pid = " << getpid() << " Waiting for interrupt." << endl;
(void) signal ( SIGALRM, child );
pause();
}
else if(pid > 0)
{ //Parent
sleep(2);
cout << "child pid = " << pid << endl;
struct sigaction act;
act.sa_handler = parent;
sigemptyset ( &act.sa_mask);
sigaction (SIGINT, &act, 0);
while(1)
{
sleep ( 1 );
}
}
return 0;
}
答案 0 :(得分:0)
好的,所以我发现了问题
当我按下^ C时,它会捕获主进程中的中断,但会终止子进程。当我从程序中运行system("ps")
时,它显示孩子a.out进程已经不存在。
为了解决这个问题,我在孩子的过程中添加了以下内容:
struct sigaction act;
act.sa_handler = CHILD_PRESERVER;
sigemptyset ( &act.sa_mask);
sigaction (SIGINT, &act, 0);
CHILD PRESERVER
是一个虚拟函数,除了保持活着之外什么都不做。
它没有看到这个解决方案非常优雅,所以如果有人有更正确的方法,请发布它。
答案 1 :(得分:0)
只需使用sigaction
signal(SIGINT, SIG_IGN);
解决方案相同的操作
最初绊倒你的事情(并经常惹恼处理ctrl-C和信号的新程序员)是ctrl-C向AN ENTIRE PROCESS GROUP发送信号,而不是发送到单个进程 - 每个进程都在该小组将获得信号。信号发送到的进程组是终端的前台进程组。
因此,这为您提供了许多处理/控制ctrl-C中断的方法。您可以让每个进程安装自己的SIGINT处理程序(就像您所做的那样)。或者您可以仔细管理您的流程组,将孩子放入他们自己的流程组(通常不是前台流程组),因此他们不会首先获得信号。
您可以使用setpgrp(2)/ setpgid(2)系统调用来管理进程组。