系统调用signal()为什么不调用处理程序?

时间:2015-11-03 00:46:30

标签: c linux signals ipc

我试图在4个进程(3个孩子+ 1个父亲)之间处理信号SIGTERM和SIGUSR1,但我不知道为什么signal()没有调用处理程序。有人能帮助我吗?

输出就像我期望的那样:

pid of father of all: 13192
The father 13192 is waiting to all children die to too
Child1: pid = 13196 - parent's pid: 13192
Child2: pid = 13197 - parent's pid: 13192
Child3: pid = 13198 - parent's pid: 13192
Sending user signal
user signal sent
Into the interrupt_handler
The child1 13196 is going to be killed immediately
The child2 13197 is going to be killed later
The child2 13197 is going to kill itself now
Child3: pid = 13198 - parent's pid: 13192
Sending user signal
user signal sent
Into the interrupt_handler
The child3 13198 is going to be killed immediately

这是我得到的输出:

pid of father of all: 13192
The father 13192 is waiting to all children die to too
Child1: pid = 13196 - parent's pid: 13192
Child2: pid = 13197 - parent's pid: 13192
Child3: pid = 13198 - parent's pid: 13192
Sending user signal
user signal sent
Child1: pid = 13196 - parent's pid: 13192
Child2: pid = 13197 - parent's pid: 13192
Child3: pid = 13198 - parent's pid: 13192
Sending user signal
user signal sent
Child1: pid = 13196 - parent's pid: 13192
...

如您所见,尚未调用interrupt_handler来处理信号。这就是问题所在。

这是我的全部代码:

#include <errno.h>              // errno and error codes
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>             // for fork()
#include <stddef.h>
#include <float.h>
#include <sys/types.h>          // for wait()
#include <sys/stat.h>
#include <sys/ipc.h>            // for all IPC function calls
#include <sys/shm.h>            // for shmget(), shmat(), shmctl()
#include <sys/sem.h>            // for semget(), semop(), semctl()
#include <sys/wait.h>           // for wait()
#include <sys/unistd.h>
#include <signal.h>             // for kill(), sigsuspend(), others

pid_t child1, child2, child3;

int count_tens=0;

void interrupt_handler(int signal){

    printf("Into the interrupt_handler\n");

    if (signal==SIGUSR1)
    {
        count_tens++;

        if(count_tens==1)
        {
            printf("The child1 %d is going to be killed immediately\n",getpid());
            if(!kill(child1,SIGKILL))
                perror("Did not kill (1)");//kills child1
            printf("The child2 %d is going to be killed later\n",getpid());
            if(!kill(child2,SIGTERM))
                perror("Did not kill (2)");//let the child2 goes through interrupt_handler

        } else if(count_tens==2)
        {
            printf("The child3 %d is going to be killed immediately\n",getpid());
            //main(); //restart application
            raise(SIGKILL); //child3 dies. At this point all children have died.

        }
    }

    if (signal==SIGTERM){
        printf("The child2 %d is going to kill itself now\n",getpid());
        raise(SIGKILL);
    }
}

int main(){

    if ((signal(SIGTERM, interrupt_handler) == SIG_ERR) || (signal(SIGUSR1, interrupt_handler) == SIG_ERR)) {
        printf("Error while setting a signal handler\n");
        exit(EXIT_FAILURE);
    }

    child1=fork();
    if (child1<0) { perror("fork"); exit(errno);}
    if(child1==0){
        while(1){
            sleep(4);
            printf("Child1: pid = %d - parent's pid: %d\n",getpid(),getppid());
        }
    }

    child2=fork();
    if(child2<0) { perror("fork"); exit(errno);}
    if(child2==0){
        while(1){
            sleep(5);
            printf("Child2: pid = %d - parent's pid: %d\n",getpid(),getppid());
        }
    }

    child3=fork();
    if(child3<0) { perror("fork"); exit(errno);}
    if(child3==0){
        while(1){
            sleep(6);
            printf("Child3: pid = %d - parent's pid: %d\n",getpid(),getppid());
            printf("Testando: Child1 pid = %d, Child2 pid = %d, Child3 pid = %d\n",child1,child2,child3);
                printf("Sending user signal\n");
                kill(getppid(), SIGUSR1);
                printf("user signal sent\n");
        }
    }

    printf("pid of father of all: %d\n",getpid());
    printf("The father %d is waiting to all children die to too\n",getpid());
    waitpid(child3, NULL, 0); // PARENT blocks until 3th CHILD ends
    return 0;
}

1 个答案:

答案 0 :(得分:0)

处理程序将由接收信号的进程执行。

要杀死孩子3,可以使用kill(child3,SIGKILL)代替raise(SIGKILL);

在该程序的第一个信号中,处理程序将由父亲调用,因为父亲收到了第一个信号(SIGUSR1),所以做raise(SIGKILL);父亲正在自杀。

以下是整个代码:

#include <errno.h>              // errno and error codes
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>             // for fork()
#include <stddef.h>
#include <float.h>
#include <sys/types.h>          // for wait()
#include <sys/stat.h>
#include <sys/ipc.h>            // for all IPC function calls
#include <sys/shm.h>            // for shmget(), shmat(), shmctl()
#include <sys/sem.h>            // for semget(), semop(), semctl()
#include <sys/wait.h>           // for wait()
#include <sys/unistd.h>
#include <signal.h>             // for kill(), sigsuspend(), others

pid_t child1, child2, child3;

int count_tens=0;

void interrupt_handler(int signal){

    printf("Into the interrupt_handler\n");

    if (signal==SIGUSR1)
    {
        count_tens++;

        if(count_tens==1)
        {
            printf("The child1 %d is going to be killed immediately\n",child1);
            if(kill(child1,SIGKILL)==-1)
                perror("Did not kill (1)");//kills child1
            printf("The child2 %d is going to be killed later\n",child2);
            if(kill(child2,SIGTERM)==-1)
                perror("Did not kill (2)");//let the child2 goes through interrupt_handler

        } else if(count_tens==2)
        {
            printf("The child3 %d is going to be killed immediately\n",child3);
            //main(); //restart application
            if(kill(child3,SIGKILL)==-1)
                perror("Did not kill (3)");//kills child3. At this point all children have died.
        }
    }

    if (signal==SIGTERM){
        printf("The child2 %d is going to be killed now\n",getpid());
        if(raise(SIGKILL)==-1)
            perror("Did not kill (4)");//let the child2 goes through interrupt_handler
    }
}

int main(){

    if ((signal(SIGTERM, interrupt_handler) == SIG_ERR) || (signal(SIGUSR1, interrupt_handler) == SIG_ERR)) {
        printf("Error while setting a signal handler\n");
        exit(EXIT_FAILURE);
    }

    child1=fork();
    if (child1<0) { perror("fork"); exit(errno);}
    if(child1==0){
        while(1){
            sleep(4);
            printf("Child1: pid = %d - parent's pid: %d\n",getpid(),getppid());
        }
    }

    child2=fork();
    if(child2<0) { perror("fork"); exit(errno);}
    if(child2==0){
        while(1){
            sleep(5);
            printf("Child2: pid = %d - parent's pid: %d\n",getpid(),getppid());
        }
    }

    child3=fork();
    if(child3<0) { perror("fork"); exit(errno);}
    if(child3==0){
        while(1){
            sleep(6);
            printf("Child3: pid = %d - parent's pid: %d\n",getpid(),getppid());
            printf("Sending user signal\n");
            if(kill(getppid(), SIGUSR1)==-1)
                perror("Did not kill (5)");//kills child3
                printf("user signal sent\n");
        }
    }

    printf("pid of father of all: %d\n",getpid());
    printf("The father %d is waiting to all children die to too\n",getpid());
    while(wait(NULL)!=-1);
    printf("The father %d is going to die\n",getpid());
    exit(0);
}