由于在信号处理期间自动屏蔽了正在被处理的信号,而使用setjmp/longjmp跳出信号处理程序时又不会自动将

信号屏蔽码修改会原来的屏蔽码,从而引起该信号被永久屏蔽。

可以使用sigsetjmp/siglongjmp来解决这一问题。

 

int sigsetjmp(sigjmp_buf env, int savesigs);

void siglongjmp(sigjmp_buf env, int val);

如果savesigs非0,则sigsetjmp在env中保存进程的当前信号屏蔽字,在调用siglongjmp会从其中恢复保存的信号

屏蔽字。

#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

#define ENV_UNSAVE 0
#define ENV_SAVED 1

int flag_saveenv = ENV_UNSAVE;
jmp_buf env;  //保存待跳转位置的栈信息

void hand_min15(int);


int main()
{
    switch(sigsetjmp(env, 1))
    {
        case 0:
        {
            printf("sigsetjmp\n");
            flag_saveenv = ENV_SAVED;
            break;
        }
        case 1:
        {    
            printf("return from min+15\n");
            break;
        }
        default:
            break;
    }

    signal(SIGRTMIN+15, hand_min15);

    
    printf("wait for signal\n");
    while(1);

    return 0;
}

void hand_min15(int sig_num)
{
    if (flag_saveenv = ENV_UNSAVE)
    {
        return;
    }

    sleep(10);
    printf("after sleep\n");
    siglongjmp(env, 1);
    printf("recv min+15\n");
    return;
}

 

说明:

1、

信号处理函数先检查 flag_saveenv 的值是否为ENV_UNSAVE,如果是,则直接返回,因为此时程序还没来得及保存返回点的栈状态信息。在sigsetjmp之后才将

flag_saveenv设置为ENV_SAVED。如果不这样处理,那么当信号发生在调用sigsetjmp之前时,信号处理函数将返回到未知地点或程序崩溃(可以在sigsetjmp前面加上sleep(20),

可以观察到程序崩溃)。使用siglongjmp从信号处理程序返回时都应该这样处理。

 

2、

实时信号是可靠的,支持排队

 

3、

 

posted on 2017-04-10 17:35  邶风  阅读(2432)  评论(0编辑  收藏  举报