alarm实现sleep

#include<setjmp.h>
#include<signal.h>
#include<unistd.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;

static sigjmp_buf env_alrm;
static volatile sig_atomic_t canjump;

//typedef void (*Sigfunc)(int);
sighandler_t old_handler = NULL;

static void sig_alrm(int signo){
    if(canjump == 0){
        cout<<"sigsetjmp is not initialized"<<endl;
        return;
    }
    cout<<"sig_alrm starting"<<endl;
    canjump = 0;
    siglongjmp(env_alrm,1);
}

unsigned int sleep2(unsigned int nesc){
    unsigned int pre_alrm;
    old_handler= signal(SIGALRM,sig_alrm);
    if(old_handler== SIG_ERR)
        return  nesc;
    pre_alrm = alarm(0);
    if(sigsetjmp(env_alrm,1)){
        if(signal(SIGALRM,old_handler) == SIG_ERR){
            cout<<"Restore default func failed"<<endl;
            exit(-1);
         }
         unsigned int tmp = alarm(0);
         if(pre_alrm>nesc){
            cout<<"Restore alarm default,pre_alrm: "<<pre_alrm<<"\n nesc: "<<nesc<<endl;
            return (alarm(pre_alrm-nesc));
         }
         return tmp;
    }
    canjump = 1;  //Initialize OK
    if(pre_alrm)
        alarm(pre_alrm<nesc?pre_alrm:nesc);
    else
        alarm(nesc);
    pause();
}

static void sig_alrm_main(int signo){
    cout<<"Main alrm starting"<<endl;
}

int main(int argc, char* argv[]){
    unsigned int unslept;
    if(signal(SIGALRM,sig_alrm_main) == SIG_ERR){
        cout<<"Caught ALRM signal ERR"<<endl;
        exit(-1);
    }
    alarm(10);
    unslept = sleep2(5);
    cout<<"sleep2 returned: "<<unslept<<endl;
    sleep(7);
    exit(0);
}
/*
在UNIX环境高级编程那本书中,使用setjmp及longjmp;但是使用setjmp及longjmp会导致信号只会接收一次,因为进入第一次进入信号处理函数之后,SIGALRM被加入进程 的信号屏蔽字,同时通过longjmp会跳出信号处理程序,此时SIGALRM仍在信号屏蔽字里,导致无法获取到后续的SIGALRM信号。因此使用专门的sigsetjmp */
posted @ 2017-06-21 16:34  舒克_贝塔  阅读(441)  评论(0编辑  收藏  举报