2011-12-28 69 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