相关函数:longjmp, siglongjmp, setjmp
表头文件:#include
函数定义:int sigsetjmp(sigjmp_buf env, int savesigs)
函数说明:sigsetjmp()会保存目前堆栈环境,然后将目前的地址作一个记号,而在程序其他地方调用siglongjmp()时便会直接跳到这个记号位置,然后还原堆栈,继续程序好执行。
参数env为用来保存目前堆栈环境,一般声明为全局变量
参数savesigs若为非0则代表搁置的信号集合也会一块保存
当sigsetjmp()返回0时代表已经做好记号上,若返回非0则代表由siglongjmp()跳转回来。
返回值:返回0代表局促存好目前的堆栈环境,随时可供siglongjmp()调用, 若返回非0值则代表由siglongjmp()返回
附加说明:setjmp()和sigsetjmp()会令程序不易令人理解,请尽量不要使用
//测试代码
#include
#include
#include
#include
#include
static jmp_buf env_alrm;
void alarm_fun()
{
printf ( "time out\n" );
siglongjmp ( env_alrm, 1 );
}
int test_alrm()
{
int test_value = 0;
signal ( SIGALRM, alarm_fun );
if ( sigsetjmp ( env_alrm, 1 ) != 0 )
{
alarm ( 0 );
signal ( SIGALRM, SIG_IGN );
return -1; /* timeout */
}
alarm ( 5 ); //5 sec;
sleep ( 10 ); //改变这里看效果
alarm ( 0 );
signal ( SIGALRM, SIG_IGN ); //忽略信号
return 1;
}
int main()
{
printf ( "%d", test_alrm() );
return 0;
}
在信号处理函数调用之前,系统自动阻塞当前被处理的信号以防止接下来发生的该类信号中断信号处理函数,这使得使用longjmp从信号处理函数返回时,出现是否恢复信号掩码的问题。有些系统恢复,有些系统不恢复,POSIX.1对此没有指示,而是提供了另外两个函数sigsetjmp和siglongjmp。当从信号处理函数跳出时,应该使用siglongjmp函数。
int sigsetjmp( sigjmp_buf * env, int savemask );
void siglongjmp ( sigjmp_buf * env, int val );
当调用sigsetjmp时,参数savemask指示是否将当前进程的信号掩码存储在env中;
在调用siglongjmp时,若env中有之前存储的信号掩码,则恢复进程的信号掩码。
在信号处理函数中调用siglongjmp时,需要特殊的保护方案:
通常在sigsetjmp调用之前部署信号处理函数,若在sigsetjmp初始化sigjmp_buf之前,信号发生,信号处理函数中的siglongjmp被调用,这将会出错。需要提供一种保护机制,保证在sigsetjmp完成之前,信号处理函数中的siglongjmp不会被调用。ISO C提供了一种sig_automic_t可以原子的写。全局定义一个sig_atomic_t类型的数据canjmp,初始值为0,在sigsetjmp完成之后将其值修改为1,在信号处理函数里面当且仅当canjmp不为0时,才回调用siglongjmp,这样就确保了在sigsetjmp调用之后才会对siglongjmp调用。通常也将canjmp限定为volatile(它被两个线程同时访问:主线程和信号处理函数)。
阅读(2334) | 评论(0) | 转发(0) |