can';不要让alarm()工作两次以上

can';不要让alarm()工作两次以上,c,alarm,setjmp,C,Alarm,Setjmp,当我运行这段代码时,程序只经过AlarmHandler一次,然后它就停留在while循环中。有人能解释一下原因吗?您的程序在某些POSIXy操作系统上可能会像您预期的那样工作——事实上,它在我正在输入的计算机上确实像您预期的那样工作。然而,它依赖于一系列与信号相关的未指定行为,我认为您已经被其中一种行为绊倒了:我认为在您的计算机上,当信号处理程序正在执行时,信号被“阻止”——它无法再次传递,而且,使用longjmp跳出处理程序不会解除信号的阻止。因此,循环一次,第二个SIGALRM就永远不会被传

当我运行这段代码时,程序只经过AlarmHandler一次,然后它就停留在while循环中。有人能解释一下原因吗?

您的程序在某些POSIXy操作系统上可能会像您预期的那样工作——事实上,它在我正在输入的计算机上确实像您预期的那样工作。然而,它依赖于一系列与信号相关的未指定行为,我认为您已经被其中一种行为绊倒了:我认为在您的计算机上,当信号处理程序正在执行时,信号被“阻止”——它无法再次传递,而且,使用
longjmp
跳出处理程序不会解除信号的阻止。因此,循环一次,第二个SIGALRM就永远不会被传递,因为它被阻塞了。还有其他几个相关的问题

您可以确定所有未指定的行为,并使程序在所有POSIXy操作系统上都可靠,但您必须使用不同的函数来设置:和。你也应该改用它来摆脱忙碌的等待。更正后的程序将如下所示:

static void AlarmHandler(int sig) ;
int i=0;
jmp_buf mark;

int main(int argc, char * argv[]){
 setjmp(mark);
 signal(SIGALRM, AlarmHandler); 
 alarm(2); 
 while(1);
 return 0;
}

static void AlarmHandler(int sig) { 
  signal(SIGALRM, SIG_IGN);           
  printf("I am in AlarmHandler:  %d \n",i);
  i++;
  longjmp(mark, 0);
} 
定义源代码700
#包括
#包括
#包括
#包括
静态jmp_buf标记;
静态空隙
手柄信号(内部信号)
{
静态整数信号计数;
信号_计数++;
printf(“SIGALRM#%u\n”,信号计数);
siglongjmp(标记、信号计数);
}
int
主(空)
{
sigset_t掩模,OMAK;
sigpemptyset(&mask);
sigaddset(&mask,SIGALRM);
if(sigprocmask(SIG_块、掩码和OMAK)){
perror(“sigprocmask”);
返回1;
}
struct-sigaction-sa;
sigfillset(和sa.sa_掩码);
sa.sa_flags=0;//不中断阻塞系统调用
sa.sa_handler=handle_SIGALRM;
if(sigaction(SIGALRM和sa,0)){
佩罗尔(“sigaction”);
返回1;
}
如果(sigsetjmp(标记,1)>=4)
返回0;
警报(1);
sigssuspend&omak;
佩罗尔(“不应该到这里”);
返回1;
}

我可能应该说几句关于信号安全的话:在这个程序中,从信号处理程序调用
printf
siglongjmp
是安全的,因为我已经安排了SIGALRM只能在执行的主线程在
sigssuspend
上被阻塞时交付。(这就是调用
sigprocmask
up top所做的。)如果您在主执行线程中除了睡眠等待信号到达之外还有其他事情要做,那么您必须了解您在信号处理程序中所做的事情,我主张使用和/或,而不是跳出处理程序,如果可能的话。

您的
i
应该是
volatile sig\u atomic\u t
。还有,为什么要使用
setjmp
/
longjmp
?这可以通过更简洁的方式实现……而且您不应该在信号处理程序中使用库函数。参考:@EugeneSh。这不是我正在做的计划。这正是我遇到麻烦的部分
setjmp/longjmp
在这里确实是不必要的,但我确实需要它。
#define _XOPEN_SOURCE 700
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
#include <unistd.h>

static jmp_buf mark;

static void
handle_SIGALRM(int sig)
{
  static int signal_count;

  signal_count++;
  printf("SIGALRM #%u\n", signal_count);
  siglongjmp(mark, signal_count);
}

int
main(void)
{
  sigset_t mask, omask;
  sigemptyset(&mask);
  sigaddset(&mask, SIGALRM);
  if (sigprocmask(SIG_BLOCK, &mask, &omask)) {
    perror("sigprocmask");
    return 1;
  }

  struct sigaction sa;
  sigfillset(&sa.sa_mask);
  sa.sa_flags = 0; // DO interrupt blocking system calls
  sa.sa_handler = handle_SIGALRM;
  if (sigaction(SIGALRM, &sa, 0)) {
    perror("sigaction");
    return 1;
  }

  if (sigsetjmp(mark, 1) >= 4)
    return 0;
  alarm(1);
  sigsuspend(&omask);

  perror("shouldn't ever get here");
  return 1;
}