gpt4 book ai didi

无法让 alarm() 工作两次以上

转载 作者:太空宇宙 更新时间:2023-11-04 02:27:34 27 4
gpt4 key购买 nike

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);
}

当我运行这段代码时,程序只通过 AlarmHandler 一次,然后它就停留在 while 循环中。谁能解释一下为什么?

最佳答案

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

您可以确定所有未指定的行为并使程序在所有 POSIXy 操作系统上都可靠,但是您必须使用不同的函数来进行设置:sigsetjmpsigaction .您还应该使用 sigsuspend 摆脱忙碌等待反而。更正后的程序看起来像这样:

#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;
}

关于信号安全,我应该说几句:在这个程序中,调用printfsiglongjmp安全的 来自信号处理程序,因为我已安排 SIGALRM 可交付,而执行的主线程在 sigsuspend 上被阻塞。 (这就是顶部调用 sigprocmask 所做的事情。)如果您在执行的主线程中有任何事情要做除了 sleep 等待信号到达,您将有待much more careful关于你在信号处理程序中做了什么,我会提倡使用 pselect和/或 self-pipe trick如果可能的话,而不是跳出处理程序。

关于无法让 alarm() 工作两次以上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48895014/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com