函数 setjmp, longjmp, sigsetjmp, siglongjmp

   一,相关函数接口

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
");
    longjmp(jmp,1);     //直接返回,后面不再执行
    printf("fun1 continue
");
}
void fun2()
{
    printf("fun2 done
");
    longjmp(jmp,2);     //直接返回,后面不再执行
    printf("fun2 continue
");
}
int main()
{
    switch(setjmp(jmp)){
        case 1:
            printf("main case 1
");
            return;
        case 2:
            printf("main case 2
");
            fun1();
            return;
        default:
            printf("default
");
            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
");
	longjmp(jmp,1);
}
inline void err_sys(char *str)
{
	printf("%s
",str);
	exit(-1);
}

int main()
{
	sigset_t oset;
	sigprocmask(0,NULL,&oset);
	if(sigismember(&oset,SIGALRM)) printf("SIGALRM in oset
");
	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
");
		err_sys("timeout");
	}
	int a=alarm(3);
	printf("%d
",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
");
	siglongjmp(jmp,1);
}
inline void err_sys(char *str)
{
	printf("%s
",str);
	exit(-1);
}

int main()
{
	sigset_t oset;
	sigprocmask(0,NULL,&oset);
	if(sigismember(&oset,SIGALRM)) printf("SIGALRM in oset
");
	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
");
		err_sys("timeout");
	}
	int a=alarm(3);
	printf("%d
",a);
	sleep(4);
	alarm(0);
	signal(SIGALRM,prefun);
	return 0;
}

 0
sig alrm
timeout

原文地址:https://www.cnblogs.com/jokoz/p/4729128.html