signal函数与setjmp&longjmp

先放定义

1. signal函数

#include<singal.h>
void (*signal(int signo, void(*func)(int))(int);

       函数原型主体部分是signal(int signo, void (*func)(int)),其中signo就是要设置的信号名参数,而func函数是针对signo信号的处理方式。func可以是常量SIG_IGN、SIG_DFL或者一个函数地址,分别代表:忽视该信号、使用系统默认方式处理该信号、使用指定函数处理该信号。看到此处如果还不理解可以继续往下看或者参考APUE10.3节内容。

2.setjmp和longjmp

#include<setjmp.h>
int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

       先说参数,env是一种jump_buf类型的变量,它是某种形式的数组,存放在调用longjmp时能够用来回复栈状态的所有信息,一般是全局变量。val是一个整型变量。

       再说用法。setjmp设置一个标记位置,程序通过longjmp可以跨越函数调到这个标记位置处执行。其中setjmp的返回 值就是longjmp的val变量。通过不同val值的longjmp跳跃,setjmp可以返回不同值,从而进行不同的处理。

       同样,可以参考apue7.10节内容。

用法

下面结合apue的图10-8程序来说一下我的理解。

1. 图10-8

#include<setnmp.h>
#include<signal.h>
#include<unistd.h>

static jmp_buf env_alrm;

static void sig_alrm(int signo)
{
    long jmp(env_alrm, 1);
}

unsigned int sleep2(unsigned int seconds)
{
    if(signal(SIGALRM, sig_alrm) == SIG_ERR)
        return(seconds);
    if(setjmp(env_alrm) == 0)
    {
        alarm(seconds);
        pause();
    }
    return(alarm(0));
}

2. 程序流程

          当sleep2被调用时发生以下情况。

          1)首先执行 第一个if内的signal运行,它将SIGALRM(闹钟信号)设置成:当SIGALRM发生时,捕获该信号,并用sig_alrm信号处理程序处理该信号。signal设置失败,则返回SIG_ERR,从而让if语句返回return(seconds)函数。如果设置成功,那么程序执行下一个if。注意:signal设置成功之后,sig_alrm在SIGALRM信号发生时自动调用,signal函数的作用只是设置好要调用的信号处理程序。

           2)第二个if内的setjmp函数执行,注意,此时是程序顺序执行到此处,setjmp函数返回值为0。如果是从longjmp返回到此处,那么setjmp返回值为longjmp的参数val。

           3)执行alrm(seconds)函数,它设置一个seconds的倒计时。如果超时则内核将发生一个SIGALRM信号。

           4)这一步将是不确定的,有两种情况。第一种是顺序执行pause()。它阻塞程序的运行,知道有一个信号发生,在这里就是SIGALRM的发生。有信号发生后,程序顺序执行return(alrm(0))。第二中情况是在程序调用pause()前,SIGALRM已经 发生。这是有可能的一种情况,特别是当系统比较繁忙的时候。CPU可能在执行完alarm之后,就去处理其他程序了,然后又在alarm超时之后回来本程序。此时,pause还没有运行,但SIGALRM已经 发生,那么程序就会调用信号处理程序sig_alrm,它又调用longjmp返回到第二个if的setjmp,setjmp返回val值(此处为1)。第二个if的判断式不成立,程序执行return(alarm(0))。

注:alarm、pause等函数如有不懂请自行百度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值