Linux系统调用--signal、setjmp、longjmp、alarm和sleep

分析以下代码的输出:

#include 
#include 
#include 
#include 
#include 
#include 

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

考察点:signalsetjmplongjmpalarmsleep函数的使用
分析:
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

你可能感兴趣的:(linux)