分析以下代码的输出:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
#include <unistd.h>
#include <time.h>
static void sig_alrm(int);
static jmp_buf env_alrm;
static int t = 0;
int main(int argc, char *argv[])
{
if(signal(SIGALRM, sig_alrm) == SIG_ERR)
{
printf("signal(ALARM) error\n");
exit(1);
}
setjmp(env_alrm);
time_t tm = time(NULL);
printf("t=%u time= %s", t++, asctime(localtime(&tm)));
alarm(10);//第一次超时,会调用sig_alrm信号捕获函数。然后跳转到上面setjmp处。第二次超时时,SIGALRM信号捕获函数已经不是sig_alrm了。
sleep(20);
tm = time(NULL);
printf("end t=%u time= %s", t, asctime(localtime(&tm)));
exit(0);
}
static void sig_alrm(int signo)
{
//longjmp(env_alrm, 1);
longjmp(env_alrm, 0);
}
输出:
t=0 time= Thu Aug 3 12:36:20 2023
t=1 time= Thu Aug 3 12:36:30 2023
end t=2 time= Thu Aug 3 12:36:50 2023
考察点:signal
、setjmp
、longjmp
、alarm
和sleep
函数的使用
分析:
1 首先输出 t=0
应该没有什么异议。
2 为什么能输出 t=1
?
因为在开始的时候设置SIGALRM的信号捕获函数sig_alrm
,在这个捕获函数里,使用longjmp
使程序跳转到setjmp
的地方,从setjmp
之后的地方继续执行。所以又继续定时了10
秒,输出了t=1
。
3 输出t=1
后程序为什么不继续回到setjmp
之后的地方继续执行?而是输出了 end t=2
并且前后共耗时30
秒?
这涉及到信号捕获函数的有效性。信号捕获函数一旦被执行,如果不再重新设置信号捕获函数,那下次信号再发生了,触发的是默认的信号捕获函数------也就是会忽略这个信号,什么也不处理。此时sleep
重新被设置了20
秒。在这20
秒过程中,alarm
超时,但是不处理,再过10
秒,输出end t=2
。