1 #include <unistd.h>
2 #include <signal.h>
3 #include <setjmp.h>
4
5 static jmp_buf env_alrm; /*要在全局变量区设定env_alrm*/
6
7 static void seg_pro(int);
8
9 unsigned int
10 sleep2(unsigned sec)
11 {
12 if(signal(SIGALRM,seg_pro) == SIG_ERR)
13 return(sec);
14 if(setjmp(env_alrm)==0)
15 {
16 alarm(sec);
17 pause();
18 }
19 return(alarm(0)); /*alarm中的参数为0,作用返回上一次设定的时间值,即返回sec*/
20 }
21
22 static void
23 seg_pro(int signo)
24 {
25 longjmp(env_alrm,1);
26 }
程序中用了setjmp和longjmp的原因是:如果没有这两者那么函数可写如下:
#include <unistd.h>
#include <signal.h>
static void sig_pro(int);
unsigned int
sleep1(unsigned int sec)
{
if(signal(SIGALRM,nothing) == SIG_ERR)
return(sec);
alarm(sec);
pause();
return(sec);
}
static void
sig_pro(int signo)
{
;
}
缺少了setjmp与longjmp后alarm与pause之间产生了竞争,有两种可能1,在中断处理函数执行前,pause得到了执行;2在中断处理函数执行先于pause的执行。
对于情况1,程序没有问题程序正确执行,睡眠一定时间后返回。对于情况2由于pause想要返回,必须得到一个信号处理程序的返回。由于中断处理函数先于其执行,执行结束后pasue才得到执行,这时候pause无法得到一个信号返回,所以会永远的等待,导致进程的阻塞。
为了解决这一情况就有了sleep2,利用setjmp和longjmp,即使出现了情况2,longjmp会跳到行12处,所以不再进入15-18的结构体。
参考书籍:《LINUX环境高级编程》第二版