2016-09-05 28 views
1

我在Mac OS上运行我的C程序。我的程序的一部分如下。此代码在sigint信号上运行良好,但无法在sigkill信号上运行。在C,linux中,关于终止信号和睡眠()循环中

void sigkill(int sig){ 
    /*some code neglected*/ 
    exit(0); 
} 
void sigint(int sig){ 
    flag=1; 
} 

void alive(void) { 
    signal(SIGINT, sigint); 
    signal(SIGKILL, sigkill); 
    alarm(10); 
    while(1){ 
     //printf("%d\n",flag); 
     sleep(1); 
     if(flag==1){ 
      printf("no\n"); 
      flag=0; 
     } 
    } 
} 

我有四个问题:

  1. 起初我没写sleep(1),它可以进入功能SIGINT(),并更改标志值,我可以从printf的看到。然而,没有“不”的输出,如我所料。

  2. 我添加睡眠功能后,效果很好。我猜while循环会每隔1秒检查一次flag,如果flag = 1,输出“no”。但是,当我按ctrl + c时,似乎每次都输出“no”。为什么它不会等待一秒?

  3. 问题说:“你不应该使用sleep()'等待10秒,使用alarm(),加上一个循环。我想知道如何实现这个没有睡眠()。

  4. kill命令不能调用sigkill函数,如何解决这个问题?

+3

你不能陷入'SIGKILL'期间。你不能为'SIGKILL'设置陷阱。顺便说一句,'SIGSTOP'。 –

+0

你知道如何在没有睡眠的情况下实现它吗? –

+0

混合'alarm()'和'sleep()'不是100%可靠的。你可以使用'alarm()'和'pause()'''pause()'只在中断并且信号处理程序返回时才返回。你可以使用'select()'和'poll()'以及特定于平台的变体来执行亚秒级的睡眠。你可以使用'nanosleep()'和'usleep()'来做睡眠的纳秒和微秒分辨率(虽然精度通常不如分辨率)。如果你看起来很辛苦,那么可能会有几秒钟的睡眠。 –

回答

3
  1. 一般情况下,信号只能被“捕获”通过你的应用程序进行系统调用进入内核时。如果你做一个普​​通的while(1) { if (flag==1){...} },那永远不会调用内核。理论上,当你在while(1)循环中做外部printf时,应该调用内核,因此信号可能被捕获。
  2. sleep()被任何信号中断。检查手册页sleep(3)
  3. 检查alarm(2)的手册页。
  4. 您不能更改SIGKILL的信号处理程序,也不能更改SIGSTOP的信号处理程序。这些信号效果被硬编码到内核中。从sigaction(2)

    正负号指定信号,并且可以是除了SIGKILLSIGSTOP任何有效信号。

    不带参数的kill命令不会生成SIGKILL信号;它会生成SIGTERM

+0

我不是很了解第三个答案。如何实施它没有睡眠? –

+1

从'alarm(2)'的手册页:'alarm()安排一个SIGALRM信号以秒为单位传送给进程。 –