函数 setjmp, longjmp, sigsetjmp, siglongjmp

时间:2021-10-30 19:33:45

一,相关函数接口

1,setjmp,longjmp,sigsetjmp,siglongjmp

    #include <setjmp.h>

int setjmp(jmp_buf env);

int sigsetjmp(sigjmp_buf env, int savesigs);    //savesigs非0时,在env中保存进程当前信号屏蔽字。

void longjmp(jmp_buf env, int val);

void siglongjmp(sigjmp_buf env, int val);  //savesigs非0时,该函数会从env中恢复保存的信号屏蔽字。
2,sigprocmask

  #include<setjmp.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);    返回 0/-1;

  获取当前信号屏蔽字:how任意值,set==NULL,当前信号屏蔽字保存在*oldset中

  修改当前信号屏蔽字:*set != NULL,how: SIG_BLOCK,并集;SIG_UNBLOCK,交集;SIG_SETMASK,新值。

3,信号集管理

#include <signal.h>

int sigemptyset(sigset_t *set);清空

int sigfillset(sigset_t *set);全集

int sigaddset(sigset_t *set, int signum);添加

int sigdelset(sigset_t *set, int signum);删除

int sigismember(const sigset_t *set, int signum);测试信号是否在集合中

4,查询挂起信号集

  #include <signal.h>

  int sigpending(sigset_t *set);  返回 0/-1,*set保存挂起信号集

5,设置定时器

  #include <unistd.h>

  unsigned int alarm(unsigned int seconds);  返回 0 或者以前设置的闹钟时间的剩余秒数

  seconds定时器时间秒数

  int pause(void);  挂起调用进程直到捕捉到一个信号。

6,发送信号

  #include<signal.h>

  int raise(int signo)  给进程自身发送信号。

  int kill(pid_t pid,int signo)  发送信号给进程或组

  pid>0,发送信号给进程ID为pid的进程

  pid==0,发送进程给本组所有进程(不包括系统进程集)

  pid==-1,有权发送信号的所有进程(不包括系统进程集)

  pid<0,有权发送信号的所有进程(不包括系统进程集)和进程ID为-pid的进程

1,setjmp,longjmp一般应用

#include<stdio.h>
#include<stdlib.h>
#include<setjmp.h>
jmp_buf jmp;
void fun1()
{
printf("fun1 done\n");
longjmp(jmp,1); //直接返回,后面不再执行
printf("fun1 continue\n");
}
void fun2()
{
printf("fun2 done\n");
longjmp(jmp,2); //直接返回,后面不再执行
printf("fun2 continue\n");
}
int main()
{
switch(setjmp(jmp)){
case 1:
printf("main case 1\n");
return;
case 2:
printf("main case 2\n");
fun1();
return;
default:
printf("default\n");
break;
}
fun2();
}

default
fun2 done
main case 2
fun1 done
main case 1

2,信号处理中的应用,longjmp返回时,会把信号加入信号屏蔽字中

#include<stdio.h>
#include<stdlib.h>
#include<setjmp.h>
#include<unistd.h>
#include<signal.h>
typedef void (*sigfun)(int);
jmp_buf jmp; void sig_alrm(int signo)
{
printf("sig alrm\n");
longjmp(jmp,1);
}
inline void err_sys(char *str)
{
printf("%s\n",str);
exit(-1);
} int main()
{
sigset_t oset;
sigprocmask(0,NULL,&oset);
if(sigismember(&oset,SIGALRM)) printf("SIGALRM in oset\n");
sigfun prefun=signal(SIGALRM,sig_alrm);
if(prefun==SIG_ERR) err_sys("signal(SIGALRM) error");
if(setjmp(jmp)!=0){
sigprocmask(0,NULL,&oset);
if(sigismember(&oset,SIGALRM)) printf("SIGALRM in oset\n");
err_sys("timeout");
}
int a=alarm(3);
printf("%d\n",a);
sleep(4);
alarm(0);
signal(SIGALRM,prefun);
return 0;
}

0
sig alrm
SIGALRM in oset   说明处理的信号已经自动加入了信号屏蔽字中
timeout

2,信号处理中,使用sigsetjmp, siglongjmp可以避免“自动加入“

#include<stdio.h>
#include<stdlib.h>
#include<setjmp.h>
#include<unistd.h>
#include<signal.h>
typedef void (*sigfun)(int);
sigjmp_buf jmp; void sig_alrm(int signo)
{
printf("sig alrm\n");
siglongjmp(jmp,1);
}
inline void err_sys(char *str)
{
printf("%s\n",str);
exit(-1);
} int main()
{
sigset_t oset;
sigprocmask(0,NULL,&oset);
if(sigismember(&oset,SIGALRM)) printf("SIGALRM in oset\n");
sigfun prefun=signal(SIGALRM,sig_alrm);
if(prefun==SIG_ERR) err_sys("signal(SIGALRM) error");
if(sigsetjmp(jmp,1)!=0){
sigprocmask(0,NULL,&oset);
if(sigismember(&oset,SIGALRM)) printf("SIGALRM in oset\n");
err_sys("timeout");
}
int a=alarm(3);
printf("%d\n",a);
sleep(4);
alarm(0);
signal(SIGALRM,prefun);
return 0;
}

0
sig alrm
timeout