关于sigsetjmp,siglongjmp注意点 (UDP超时重传应用)

问题来源:UDP编程中,应用程序实现的超时重传机制,在计算每个分组的RTO时。在发送请求和接受应答之间要运用超时重传机制,来提高UDP传输的可靠性。

题外话:【Jacobson算法:每次测得一个RTT后就计算RTO以及重传时如何增加RTO。一般当定时器满,实行RTO指数回退。
Karn算法:只有收到不是重传的请求时,才更新RTT并重新计算RTO。】

使用alarm作为定时器,在对SIGALRM信号处理时,不是希望信号处理函数直接返回,而是希望跳转到主进程。这就需要用到setjmp,longjmp或sigsetjmp和siglongjmp函数。
sigsetjmp和siglongjmp函数应用于信号处理函数中的原因是,使用setjmp,longjmp并不对信号屏蔽字有处理,即捕捉到一个信号后,进入到信号处理函数,内核自动把当前信号加到进程的信号屏蔽字中,避免多次中断,然而在这个时候使用longjmp跳出信号处理函数,信号屏蔽字却没有恢复,使得进程再也捕捉不到这个信号。
int sigsetjmp(sigjmp_buf env, int savesigs);
注意点::::若直接调用则返回0,若用siglongjmp返回则返回非零值
void siglongjmp(sigjmp_buf env, int val);

若savesigs非0,则内核在env中保存了信号的屏蔽字。调用siglongjmp时,siglongjmp从env中恢复信号屏蔽字。
测试1:可以多次捕捉SIGALRM
#include "unp.h"
#include <setjmp.h>
#include <time.h>
sigjmp_buf buf;

void func(int signo){
	printf("call func\n");
	siglongjmp(buf,1);
	printf("next will return func\n");
}
int main(int argc, char **argv){
	int nsecs;
	signal(SIGALRM, func);
	alarm(3);
	if(sigsetjmp(buf, 1) == 0){/*调用*/
		printf("call success\n");
		sleep(10);
	}
	else{/*从siglongjmp返回*/
		printf("siglong jmp return\n");
		alarm(0);
		alarm(2);
		exit(0);
	}
}
测试2:第一次SIGALRM捕捉,以后都失去。
#include "unp.h"
#include <setjmp.h>
#include <time.h>
sigjmp_buf buf;

void func(int signo){
	printf("call func\n");
	longjmp(buf,1);
	printf("next will return func\n");
}
int main(int argc, char **argv){
	int nsecs;
	signal(SIGALRM, func);
	alarm(3);
	if(setjmp(buf) == 0){/*调用*/
		printf("call success\n");
		sleep(10);
	}
	else{/*从siglongjmp返回*/
		printf("siglong jmp return\n");
		sleep(0);
		alarm(2);
		alarm(1);
		sleep(5);
		exit(0);
	}
}

你可能感兴趣的:(编程,算法,测试)