2016-05-09 75 views
-1

我试图潜入C中的信号并试图理解它是如何工作的。我知道SIGKILL和SIGSTOP不能被处理/捕获。我的问题是谁能解释下面的代码中while-loop的作用?如果没有一个时间循环会怎么样。。 while循环的使用

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

void sig_handler(int signo) 
{ 
    if (signo == SIGUSR1) 
     printf("received SIGUSR1\n"); 
    else if (signo == SIGKILL) 
     printf("received SIGKILL\n"); 
    else if (signo == SIGSTOP) 
     printf("received SIGSTOP\n"); 
} 

int main(void) 
{ 
    if (signal(SIGUSR1, sig_handler) == SIG_ERR) 
     printf("\ncan't catch SIGUSR1\n"); 
    if (signal(SIGKILL, sig_handler) == SIG_ERR) 
     printf("\ncan't catch SIGKILL\n"); 
    if (signal(SIGSTOP, sig_handler) == SIG_ERR) 
     printf("\ncan't catch SIGSTOP\n"); 
    // A long long wait so that we can easily issue a signal to this process 
    while(1) 
     sleep(1); 
    return 0; 
} 
+1

当你用while()循环运行你的程序时,发生了什么事? –

回答

2

While while循环永远调用sleep(1)。在信号中断之前,进程将停止休眠,运行信号处理程序,然后在信号处理程序返回时再次休眠。

我建议将其更改为sleep(UINT_MAX)循环内。该程序将具有相同的行为,但效率更高,因为代码不需要每秒都在用户模式和内核模式之间转换。

+0

不,中断的“睡眠”不会奇迹般地重新启动!所以需要一些循环。因此,你不能用'睡眠(UINT_MAX)'来代替'while(1)sleep(1)';' –

+0

@BasileStarynkevitch:哦,我现在明白了,这个程序想要永远接收信号。好的,我会更新我的回答,以更好地反映OP的计划中发生的事情。 –

2

我假设你在Linux或某些POSIX系统上。

然后,仔细阅读​​。注意一个信号处理程序只能调用异步信号的安全函数,而printf而不是这样的函数。所以你的代码有undefined behavior,所以是非常错误的。

阅读有关<signal.h>的POSIX文档。您可能需要定义一个全局的volatile sig_atomic_t flag;并将其设置在您的信号处理程序中(并在外部进行测试,例如在poll(2)以上的某个event loop)。

while(1) 
    sleep(1); 

仅仅是围绕着sleep(3)功能的无限循环,在循环体中等待一秒钟(例如,用于信号发送,该信号将“中断”的当前呼叫sleep,但循环将重新开始,除非信号正在终止进程)。

您也可以在程序上使用strace(1)来了解涉及哪些系统调用。

顺便说一句,你可以仔细循环sigsuspend(2)(而不是sleep)。我也建议阅读Advanced Linux Programming