2014-01-23 34 views
1

在APUE SLEEP2的代碼如下:sleep2在apue中無法正常工作?

#include <setjmp.h> 
#include <signal.h> 
#include <unistd.h> 
#include <stdio.h> 

static jmp_buf env_alrm; 

static void sig_alrm(int signo) 
{ 
    longjmp(env_alrm, 1); 
} 

unsigned int sleep2(unsigned int nsecs) 
{ 
    if(signal(SIGALRM, sig_alrm) == SIG_ERR) 
    { 
     return (nsecs); 
    } 

    if(setjmp(env_alrm) == 0) 
    { 
     alarm(nsecs); 
     pause(); 
    } 

    return (alarm(0)); 
} 

int main(void) 
{ 
    while(1) 
    { 
     sleep2(1); 
     printf("test\n"); 
    } 
    return 0; 
} 

代碼的輸出僅僅是一個字符串「測試」,然後掛斷

據我瞭解,SLEEP2功能的工作原理如下:

  1. jmp_buf env_alrm被設置爲0
  2. 當在第一時間程序調用SLEEP2,所述alarm(nsecs)將被稱爲
  3. 在納秒的時間內,sig_alrm將被調用,longjpm設置env_alrm結構爲1
  4. 然後跳轉到if(setjmp(env_alrm) == 0),而事實並非如此,所以它在運行的語句return alarm(0)

當SLEEP2被稱爲第二次,結構jmp_buf env_alrm的值是1,所以alrm(nsecs)不會被調用,在我看來,這就是使得功能可按工作不正常,所以我改變了代碼如下:

#include <setjmp.h> 
#include <signal.h> 
#include <unistd.h> 
#include <stdio.h> 

static jmp_buf env_alrm; 

static void sig_alrm(int signo) 
{ 
    longjmp(env_alrm, 1); 
} 

unsigned int sleep2(unsigned int nsecs) 
{ 
    if(signal(SIGALRM, sig_alrm) == SIG_ERR) 
    { 
     return (nsecs); 
    } 

    alarm(nsecs); 
    if(setjmp(env_alrm) == 0) 
    { 
     pause(); 
    } 

    return (alarm(0)); 
} 

int main(void) 
{ 
    while(1) 
    { 
     sleep2(1); 
     printf("test\n"); 
    } 
    return 0; 
} 

然而,第二個程序會產生與第一個程序相同的輸出,所以我的問題是:

什麼使兩個程序只打印一個「測試」然後掛起?

回答

0

您的代碼與書上的代碼完全相同。每當信號處理程序longjmp()到sleep2()時,alarm()永遠不會(也不會再次)執行。對於你的問題,我建議你繼續閱讀這本書,直到sig_setjmp()函數的部分。 因爲我不知道你的系統,我認爲掛斷很可能是由於longjmp()沒有恢復信號掩碼。這意味着您第一次輸入信號處理程序時系統會自動屏蔽此信號以避免再次進入。當處理程序返回這個被屏蔽的信號(在你的情況下是SIGALRM)未被屏蔽(恢復)。 POSIX沒有定義longjmp()是否應該恢復這個信號。所以你可能在處理程序中掩蓋了SIGALRM,並且沒有揭露它。結果程序被卡在第二個循環中。 要驗證這一點,您可以在sig_alrm()處理函數中使用pr_mask()函數。這是作者編寫的用於打印當前進程的掩碼的函數。通知我結果。