2013-03-23 20 views
2

Hy每一個使用fork和signal做一些實驗的同時,我遇到了一個顯示非常有趣的行爲的程序,但是經過幾個小時的努力,我找不到什麼是發生。當使用信號捕捉叉時,程序變得無限

我想要做的是我在主體內創建一個子進程,然後打印「hello world」,然後調用exit。在這之後,人們完全明白它的信號處理程序會被調用,並且等待系統調用阻塞的父進程也會被調用。現在我正在信號處理程序中創建另一個進程,但是從那裏開始,輸出變得無限。

輸出是這樣的: 世界,你好 來用Linux快來快來UNIX到Linux快來快來UNIX到Linux來到UNIX ...

而且爲什麼來用Linux連連打印。

也請告訴我什麼時候撥號叫,我知道重複的地址空間是由父母,但信號處理程序呢?他們也有重複嗎?在我的情況下,當小孩叫退出。然後,被調用的信號處理程序是孩子或父母。

請幫忙。 謝謝。

void sig_handler(int signo) 
{ 
if(fork() == 0){ 

} 
else{ 
    int pid = 0; 
    wait(&pid); 
    printf("Come to unix"); 
    fflush(stdout); 
} 
} 


int main() 
{ 
if (signal(SIGCHLD, sig_handler) == SIG_ERR){ 
} 

int child_pid; 
int i; 

child_pid = fork(); 
switch (child_pid) { 
    case -1:   
     perror("fork"); 
     exit(1); 
    case 0:   
     printf("hello world\n");fflush(stdout);   
     exit(0); 
    default: 
     wait(&i); 
     printf("Come to linux"); 
     exit(0); 
     //break; 
} 

return 0; 
} 

回答

1

難道它會進入一個無限循環嗎?您已經創建了一個SIGCHLD處理程序,然後在該處理程序中再次分叉並等待子進程退出。基本上,當處理程序中的孩子退出時,父母再次進入處理程序。 下面的代碼應該避免它。在信號處理程序的開始處,通過將信號設置爲默認值來避免該信號。

void sig_handler(int signo) { 
    signal (SIGCHLD, SIG_IGN); 
    if(fork() == 0){ 

    } 
    else{ 
     int pid = 0; 
     wait(&pid); 
     printf("Come to unix"); 
     fflush(stdout); 
    }  
} 

而且,你只能調用異步信號安全例程的信號處理程序,以避免發生不可預料的行爲。我不確定printf和fflush是否同步安全。儘管做出上述改變避免了循環,但程序仍然可能存在未定義的行爲。 我想叉是異步安全

請參見下面的討論可能會有所幫助: http://sourceware.org/bugzilla/show_bug.cgi?id=4737

0

在信號處理程序中調用fork(2)已按照POSIX標準的未定義行爲,所以乾脆不要做它:)

參見:http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

+0

THX了很多。但應該有一些理由。 – 2013-03-23 13:08:14

+0

爲了解決這個問題,你必須看看fork和signal是如何在你的操作系統中實現的,這可能會有所不同,甚至可能在不同版本之間。我的猜測是,你的操作系統每次調用信號處理程序時都會再次調用它(在子進程中)。 – jbr 2013-03-23 13:12:56

+0

嘗試在信號處理程序的子部分輸出一些東西,這應該表明我是否正確。 – jbr 2013-03-23 13:19:33