SIGINT信号在linux中重新安装

时间:2013-10-07 08:00:11

标签: linux signals sigint

我正在编写一个处理Linux信号的程序。更具体地说,我想在子进程中重新安装信号SIGINT,但却发现它不起作用。

以下是我的代码的简单版本:

void handler(int sig){
    //do something
    exit(0);
}

void handler2(int sig){
    //do something
    exit(0);
}
int main(){

    signal(SIGINT, handler);

    if ((pid = fork()) == 0) {
        signal(SIGINT, handler2); // re-install signal SIGINT

        // do something that takes some time
        printf("In child process:\n");
        execve("foo", argv, environ); // foo is a executable in local dir

        exit(0);
    }else{
        int status;
        waitpid(pid, &status, 0); // block itself waiting for child procee to exit
    }

    return 0;
}

当shell正在打印“在子进程中:”时,按ctrl + c。我发现函数handler没有问题,但handler2永远不会被执行。

你能帮我解决一下我的代码中的这个错误吗?

更新: 我希望子进程在foo运行过程中接收SIGINT信号,这可能吗?

2 个答案:

答案 0 :(得分:1)

这不是错误 - 调用execve已取代正在运行的二进制映像。函数handler2()(以及二进制的任何其他函数)不再映射到已被“foo”图像替换的程序存储器中,因此所有信号设置都将替换为默认值。

如果希望信号处理程序在“foo”运行期间处于活动状态,则必须:

  1. 确保处理程序函数映射到foo
  2. 的内存中
  3. 在“foo”启动后注册信号处理程序。
  4. 这样做的一种方法是创建一个包含信号处理程序和init函数的共享库,该函数被定义为注册所述信号处理程序的构造函数,并通过操作它来强制它进入“foo”内存。您要execve foo(环境变量)包含

    的环境
    LD_PRELOAD=/path/to/shared_library.so
    

答案 1 :(得分:0)

@ gby的anwser给出了全面的背景知识。我在这里提供另一种没有共享库的解决方案。

每次子进程停止或终止时,父进程都将收到SIGCHLD。您可以处理此SIGCHLD信号以了解SIGINT是否终止子进程。在你的处理程序中:

pid_t pid = waitpid(pid_t pid,int * status,int options)

您可以通过waitpid函数获取子进程的状态。

if(WIFSIGNALED(status) && (pid == child_pid)){
    if(WTERMSIG(status) == SIGINT){
       // now you know your foo has received SIGINT.
       // do whatever you like.
    }
 }