2011-12-28 53 views
2

如果我發送多個後續Hangup信號,下面的程序,只有他們兩個人會被處理,其餘的將被忽略:如何捕捉兩個以上的連續信號?

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

int id; 
void handler(int s) 
{ 
    id++; 
    int i; 
    for(i=0; i<3; i++) 
    { 
     printf("Sig %d\n", id); 
     sleep(2); 
    } 
} 

int main() 
{ 
    int i; 
    signal(SIGHUP, handler); 
    for(i=0; ; i++) 
    { 
     printf("%d\n", i); 
     sleep(1); 
    } 
    return 0; 
} 

我用下面的命令來發送信號到進程:

kill -l {#process} 

如果我運行上述命令連續三次,第三信號將被忽略,因爲在下面的輸出:

0 
1 
2 
3 
4 
5 
6 
7 
Sig 1 
Sig 1 
Sig 1 
Sig 2 
Sig 2 
Sig 2 
8 
9 
10 
11 
12 

有什麼方法可以捕捉到第三個信號?

+2

睡在一個信號處理程序是值得懷疑的。它必須在那裏嗎? – wallyk 2011-12-28 08:40:06

+0

@wallyk根據手冊頁面,POSIX.1-2004要求在信號處理程序中保證'sleep'的安全。 – 2011-12-28 08:45:05

+0

正常信號不排隊,無論您做什麼,都會錯過一些信號。 – nos 2011-12-28 09:03:27

回答

2

通常情況下,你不能用標準信號做到這一點。 Unix內核通常只排隊一個待處理的信號。如果在Sig1處理程序中處理休眠時發送Sig2和Sig3,它們將被合併。

您可以使用sigaction(2)來設置您的信號處理程序併爲其提供SA_NODEFER標誌。它將允許在信號處理器中傳送新信號。確保你的處理程序是可重入的,這是一個容易出錯的解決方案。

還有POSIX.1b(POSIX.1-2001)擴展稱爲「實時信號」。這種信號可以多次排隊,但SIGHUP不是其中之一。 Linux上的信號(7)指出實時信號編號爲33(SIGRTMIN)至64(SIGRTMAX)。

1

在Linux上,未決信號僅用一位表示。這意味着如果在處理程序已經運行時生成多個信號,那麼它將只被再次調用。

+0

當我在我的linux上輸入'ulimit -a'時,我可以看到'pending signals'的默認值是16383.我用'getrlimit'和資源名'RLIMIT_SIGPENDING'(它又是16383)測試了它。那麼linux如何處理這一數量的待處理信號只有一個位? – saeedn 2011-12-28 09:43:32

+0

@saeedn這是每個用戶每個進程可以掛起的信號總數(實際上是每個「真實用戶ID」)。對於單個信號,每個過程只能有一個信號的每個類型可以掛起。 – 2011-12-28 09:50:53