2015-06-13 313 views
1

我不明白下面的代码:父进程等到子进程终止时,子进程如何才能杀死父进程?

pid_t pid; 
int counter = 0; 
void handler1(int sig) { 
    counter++; 
    printf("counter = %d\n", counter); 
    fflush(stdout); 
    kill(pid, SIGUSR1); 
} 
void handler2(int sig) { 
    counter += 3; 
    printf("counter = %d\n", counter); 
    exit(0); 
} 
int main() { 
    signal(SIGUSR1, handler1); 
    if ((pid = fork()) == 0) { 
    signal(SIGUSR1, handler2); 
    kill(getppid(), SIGUSR1); 
    while (1) { 
    }; 
    } else { 
    pid_t p; 
    int status; 
    if ((p = wait(&status)) > 0) { 
     counter += 2; 
     printf("counter = %d\n", counter); 
    } 
    } 
} 

如何可以在父进程等待,直到它的子进程终止子进程实际上杀害父进程?

+0

使用案例:家长分给孩子。孩子通过阅读配置等启动,并且只有在成功启动后才将SIGUSR1发送给父节点。在此之前,如果孩子在开始时死亡(因为它是在“wait()”中),并且在处理完SIGUSR1之后父节点终止并假定孩子会好。 –

+0

注意[如何避免在信号处理程序中使用'printf()'](http://stackoverflow.com/questions/16891019/)。 –

回答

3

首先请注意,系统调用kill()有点错误,因为它是向进程发送信号的通用函数。杀死目标进程只是几个可能的结果之一。

然而,更一般地说,信号处理是一种中断机制。收到信号可能会中断很多库函数,包括wait()。控制传递给该信号的注册处理程序(如果有的话),或者执行默认操作。之后,被中断的功能返回,通过其返回代码和/或通过设置errno指示错误。

编辑为添加:此外,您自己的代码可能会因收到信号而中断。如果结果不是终止进程,则如果信号处理程序正常退出,则执行将在其停止的位置恢复,或者在处理程序退出时通过调用longjmp()退出。

另外,信号交付是由内核处理的异步机制。一个进程可能被阻塞或以其他方式占用,并仍然接收信号;的确,这是他们重要的一部分。每个进程都有一个等待处理的未决信号队列;对于大多数进程来说,这个队列几乎总是空的,但除非你明确地阻止了信号,否则进程假定它不会收到任何信号(并且某些信号不能被阻止)是不安全的。

在您的特定代码中,主流程首先将function1()设置为其信号处理器USR1。然后它分叉,并且子进程设置功能function2()它的处理程序用于信号USR1(从而不影响父项),向父项发送信号USR1,并进入无限循环。

同时,家长为其子进程启动wait()。这将被接收信号中断。收到信号并且注册处理程序运行后,等待将结束,wait()返回-1并将errno设置为EINTR。处理程序执行的其中一个操作是发送一个SIGUSR1给孩子。

接收到信号后,孩子的正常执行流程被中断以运行其处理程序function2()。这更新孩子的变量副本counter,打印其值和exit() s。

最终结果:

主要过程打印

计数器= 1

然后退出。子进程打印

计数器= 3

然后退出。

+0

所以你的意思是即使功能kill也不能成功杀死父节点。它仍然发出信号。 – Makara

+0

@马卡拉,不,我不是那个意思。如果孩子发送了'SIGKILL'或'SIGTERM',那么它可能会导致其父母终止;这并不是它所做的。 –

+0

感谢指出,但我对结果有点混淆,为什么在我的电脑他们打印出来的结果就像counter = 1 \ n counter = 3 \ n counter = 3 \ n – Makara

相关问题