C ++ Process fork和sigalarm

时间:2012-02-15 07:05:19

标签: c++ fork

这个程序的目标是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;
}

2 个答案:

答案 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)系统调用来管理进程组。