函数 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\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);
jmp_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

时间: 2024-08-04 19:44:33

函数 setjmp, longjmp, sigsetjmp, siglongjmp的相关文章

信号处理函数的返回sigsetjmp/siglongjmp

由于在信号处理期间自动屏蔽了正在被处理的信号,而使用setjmp/longjmp跳出信号处理程序时又不会自动将 信号屏蔽码修改会原来的屏蔽码,从而引起该信号被永久屏蔽. 可以使用sigsetjmp/siglongjmp来解决这一问题. int sigsetjmp(sigjmp_buf env, int savesigs); void siglongjmp(sigjmp_buf env, int val); 如果savesigs非0,则sigsetjmp在env中保存进程的当前信号屏蔽字,在调用s

setjmp &amp; longjmp实现分析

如何使用setjmp & longjmp,就不再细说了,请参考APUE 7.10. 本文解释如下知识点:1.简单介绍X86_64的寄存器2.setjmp & longjmp是怎么实现的.3.为什么能从setjmp处多次返回.4.从setjmp返回时,那些数据是无效了,如何避免. 本文没有画出函数调用栈桢的图,如果对汇编不是很熟悉的话,最好边看边画^_^,会事关功倍. 下文是通过反汇编如下代码来分析的 #include <setjmp.h> #include <stdio.

setjmp/longjmp

1.setjmp/longjmp属于传统的错误处理 2.setjmp/longjmp是对goto语句的补充,goto只能实现局部跳转,setjmp/longjmp可以实现全局跳转 3.setjmp/longjmp与goto都有缺陷 传统错误处理的3种方式是: 1.设置全局错误状态,标准c中使用errno与perror函数来支持 2.使用标准c库中的信号 3.使用setjmp/longjmp setjmp/longjmp

Linux setjmp longjmp

/********************************************************************* * Linux setjmp longjmp * 说明: * 最近在看cmockery源代码的时候发现setjmp和longjmp函数,于是查了 * 相关的内容,发现真是个好东西,可以完成函数之间的直接跳转. * * 2016-5-7 深圳 南山平山村 曾剑锋 ************************************************

linux的setjmp函数和longjmp函数

函数原型  int setjmp(jmp_buf env) setjmp参数env的类型是一个特殊类型jmp_buf.这一数据类型是某种形式的数组,其中存放:在调用longjmp时能用来恢复栈状态的所有信息.因为需要在另一个函数中引用env变量,所以规范的处理方式是将env变量定义为全局变量.setjmp函数初次启用时返回 0 值. 函数原型  void longjmp(jmp_buf env, int val) longjmp函数的中参数env是由setjmp函数所保存的堆栈环境.参数val设

setjmp()/longjmp()的使用方法

setjmp和longjmp.为了让你实现复杂的流控制,程序在系统里面运行完全依靠内存(代码段,全局段,堆存储器,栈存储器)和寄存器的内容(栈指针,基地址,计数器),setjmp保存当前的寄存器里面的内容,longjmp是恢复这些内容.longjmp返回setjmp程序当前的状态 先看一个例子: #include <csetjmp> #include <cstdio> #include <windows.h> int main() { jmp_buf env; int

c setjmp longjmp

http://coolshell.cn/?s=setjmp http://www.cnblogs.com/hazir/p/c_setjmp_longjmp.html 1 double divide(double to, double by, jmp_buf env) 2 { 3 if(by == 0) 4 if (env) 5 longjmp(env, 1); 6 else 7 return 0; 8 else 9 return to/by; 10 } 11 12 void f() 13 { 1

《UNIX环境高级编程》读书笔记之进程环境

1.进程终止 有八种方式使进程终止 (1)从main返回 (2)调用exit; (3)调用_exit或者_Exit: (4)最后一个线程从其启动历程返回 (5)最后一个线程调用pthread_exit: 异常终止方式有三种: (6)调用abort(): (7)接到一个信号: (8)最后一个线程对取消请求做出相应 三个函数用于正常终止一个程序: #include <stdlib.h> void exit(int status); void _Exit(int status); #include

c语言setjmp与longjmp函数

我们都知道在一个函数内进行跳转,可以使用goto语句,但是如果要在函数之间跳转goto是不能完成的.要想完成函数之间的跳转我们需要借助setjmp和longjmp这两个函数连实现,这都包含在头文件setjmp.h中 函数原型: 1. int setjmp(jmp_buf env):此函数的功能是将函数在此处的上下文保存在jmp_buf结构体中,以供longjmp从此结构体中恢复.参数env即为保存上下文的jmp_buf结构体变量.如果直接调用该函数返回值为0,若该  函数从longjmp调用返回