函数setjmp,longjmp和sigsetjmp,siglongjmp
int sigsetjmp(sigjmp_buf env,int savemask);
返回值:若直接调用则返回0,若从siglongjmp调用返回则返回非0值;
int siglongjmp(sigjmp_buf env,int val);
setjmp和longjmp的使用如下:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<signal.h> #include<setjmp.h> #define MAXLINE 1024 void sig_alarm(int signo); jmp_buf env_alrm; int main() { int n; char buf[MAXLINE]; if (signal(SIGALRM, sig_alarm) == SIG_ERR) { printf("can't catch sigalrm\n"); exit(0); } if (setjmp(env_alrm) != 0) { printf("longjump called\n"); exit(0); } alarm(5); if ((n = read(STDIN_FILENO, buf, MAXLINE)) < 0) { printf("read error\n"); exit(0); } alarm(0); write(STDOUT_FILENO, buf, n); } void sig_alarm(int signo) { longjmp(env_alrm, 1); }
也可以用在sleep函数中:
#include<setjmp.h> #include<signal.h> #include<unistd.h> static jmp_buf env_alrm; static void sig_alrm(int signo) { longjmp(env_alrm, 1); } unsigned int sleep2(unsigned int secs) { if (signal(SIGALRM, sig_alrm) == SIG_ERR) { return (nsecs); } if (setjmp(env_alrm) == 0) { alarm(nsecs); pause(); } return (alarm(0)); }
sigsetjmp和siglongjmp使用基本相同,只是siglongjmp比setjmp多一个参数,若savemask为非0值,则sigsetjmp在env中保存进程的当前屏蔽字。若调用siglongjmp时,如果带非0 savemask的sigsetjmp调用已经保存了env,则siglongjmp从其中回复保存的信号屏蔽字。
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<signal.h> #include<setjmp.h> //SIGINT,SIGQUIT,SIGUSR1,SIGALRM //siglongjmp longjmp //siglongjmp can handle singal automatic void sig_alarm(int signo); void sig_usr1(int signo); void pr_mask(const char *str); jmp_buf jmp_aaa; static int canjmp = 0; int main() { pr_mask("start pro"); if (signal(SIGALRM, sig_alarm) == SIG_ERR) { printf("can't catch sigalrm\n"); exit(0); } if (signal(SIGUSR1, sig_usr1) == SIG_ERR) { printf("can't catch sigusr1\n"); exit(0); } if (sigsetjmp(jmp_aaa, 1) != 0) { //if (setjmp(jmp_aaa) != 0) { pr_mask("end pro"); exit(0); } canjmp = 1; raise(SIGUSR1); return 0; } void sig_alarm(int signo) { pr_mask("in sig_alarm"); } void sig_usr1(int signo) { if (canjmp == 0) { return; } pr_mask("before sigalrm"); alarm(3); sleep(5); pr_mask("after sigalrm"); siglongjmp(jmp_aaa, 1); //longjmp(jmp_aaa, 1); } void pr_mask(const char *str) { printf("%s\n", str); sigset_t curset; if (sigprocmask(0, NULL, &curset) < 0) { printf("call sigprocmask error\n"); } if (sigismember(&curset, SIGINT)) printf("SIGINT\n"); if (sigismember(&curset, SIGQUIT)) printf("SIGQUIT\n"); if (sigismember(&curset, SIGUSR1)) printf("SIGUSR1\n"); if (sigismember(&curset, SIGALRM)) printf("SIGALRM\n"); }