2015-06-13 311 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

相關問題