`

sigsetjmp 和 siglongjmp 函数

阅读更多
    在非局部跳转函数 setjmp 和 longjmp 介绍一节中曾提到用于在普通函数中进行非局部转移的 setjmp 和 longjmp 函数,POSIX.1 没有指定指定这两个函数对信号屏蔽字的作用,而是定义了两个新函数 sigsetjmp 和 siglongjmp。在信号处理程序中进行非局部转移时应当使用这两个函数。
#include <setjmp.h>
int sigsetjmp(sigjmp_buf, int savemask);
              /* 返回值:若直接调用,返回 0;若从 siglongjmp 调用返回,则返回非 0 */
void siglongjmp(sigjmp_buf env, int val);

    这两个函数与 setjmp、longjmp 之间的唯一区别是 sigsetjmp 增加了一个参数:如果 savemask 非 0,则 sigsetjmp 在 env 中保存进程的当前信号屏蔽字,以便调用 siglongjmp 时从其中恢复保存的信号屏蔽字。
    下面这个程序演示了在信号处理程序被调用时,系统所设置的信号屏蔽字如何自动地包括被捕捉到的信号。
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <setjmp.h>
#include <errno.h>

// extern void pr_mask(const char *);
void pr_mask(const char *str){
	sigset_t	sigset;
	int		errno_save;

	errno_save = errno;		// we can be called by signal handlers
	if(sigprocmask(0, NULL, &sigset) < 0){
		printf("sigprocmask error\n");
	}else{
		printf("%s", str);
		if(sigismember(&sigset, SIGINT))
			printf(" SIGINT");
		if(sigismember(&sigset, SIGQUIT))
			printf(" SIGQUIT");
		if(sigismember(&sigset, SIGUSR1))
			printf(" SIGUSR1");
		if(sigismember(&sigset, SIGALRM))
			printf(" SIGALRM");

		/* remaining signals can go here */

		printf("\n");
	}
	errno = errno_save;		// restroe errno
}

static sigjmp_buf	jmpbuf;
static volatile sig_atomic_t	canjump;

static void sig_usr1(int signo){
	if(canjump == 0)
		return;			// unexpected signal, ignore
	pr_mask("starting sig_usr1:");

	alarm(3);			// SIGALRM in 3 seconds
	time_t starttime = time(NULL);
	for(;;)				// busy wait for 5 seconds
		if(time(NULL) > starttime + 5)
			break;
	pr_mask("finishing sig_usr1:");
	canjump = 0;
	siglongjmp(jmpbuf, 1);	// jump back to main, don't return
}

static void sig_alrm(int signo){
	pr_mask("in sig_alrm:");
}

int main(void){
	if(signal(SIGUSR1, sig_usr1) ==	SIG_ERR)
		printf("signal(SIGUSR1) error\n");
	if(signal(SIGALRM, sig_alrm) == SIG_ERR)
		printf("signal(SIGALRM) error\n");
	pr_mask("starting main:");
	if(sigsetjmp(jmpbuf, 1)){
		pr_mask("ending main:");
		exit(0);
	}
	canjump = 1;	// now sigsetjmp() is OK
	for(;;)
		pause();
}

    此程序中演示了另一种只要在信号处理程序中调用 siglongjmp 就应使用的技术:仅在调用 sigsetjmp 之后才将变量 canjump 设置为非 0,在信号处理程序中检测此变量,仅当它为非 0 时才调用 siglongjmp。这提供了一种保护机制,以免 jmpbuf 还未初始化时就调用信号处理程序,因为信号可能在任何时候发生。
    另外,程序中使用了数据类型 sig_atomic_t,在写这种类型的变量时不会被中断。这意味着这种变量在具有虚拟存储器的系统上不会跨越页边界,可以用一条机器指令对其进行访问。这种类型的变量总是包括类型修饰符 volatile,其原因是:该变量将由两个不同的控制线程 main 函数和异步执行的信号处理程序访问。
    下图显示了此程序的执行时间顺序。在进程执行左面部分时(对应 main),信号屏蔽字是 0(无信号被阻塞);执行中间部分是(对应 sig_usr1),其信号屏蔽字是 SIGUSR1;执行右面部分时(对应 sig_alrm),其信号屏蔽字是 SIGUSR1 和 SIGALRM。

    运行该程序的结果如下。
$ ./sigjump.out &                    # 在后台启动程序
[1] 16011
$ starting main:                     # 这是 main 函数的输出
$
$ kill -USR1 16011                   # 向该后台进程发送 SIGUSR1 信号
starting sig_usr1: SIGUSR1
in sig_alrm:  SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1
ending main: 
[1]+  Done                    ./sigjump.out

    可见该输出与所期望的相同:当调用一个信号处理程序时,被捕捉到的信号会自动加到进程的当前信号屏蔽字中。当从信号处理程序返回时,siglongjmp 恢复了 sigsetjmp 所保存的信号屏蔽字。
    如果在 Linux 中将该程序中的 sigsetjmp 和 siglongjmp 分别替换成 setjmp 和 longjmp,则最后一行输出将变成:
            ending main: SIGUSR1
     这意味着在调用 setjmp 之后执行 main 函数时,其 SIGUSR1 是阻塞的,这多半不是所期望的。
  • 大小: 6.7 KB
分享到:
评论

相关推荐

    LINUX环境高级编程 第五章 信号

    信号的概念 signal函数 不可靠信号与可靠信号 信号的发送接收机制 信号集与可靠信号机制 sigsetjmp和siglongjmp函数 abort函数

    Linux操作系统下C语言编程入门

    - 为了确保信号处理的安全性,示例还展示了如何使用 `sigsetjmp` 和 `siglongjmp` 来实现非局部跳转,从而在信号处理函数中安全地恢复之前的执行状态。 综上所述,这些知识点涵盖了 Linux 下 C 语言编程的基本信号...

    UNIX环境高级编程_第二版中文

    10.15 sigsetjmp和siglongjmp函数  10.16 sigsuspend函数  10.17 abort函数  10.18 system函数  10.19 sleep函数  10.20 作业控制信号  10.21 其他特征  10.22 小结  习题  第11章 线程  11.1 ...

    UNIX环境高级编程 pdf格式

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.22 小结 244 习题 244 第11章 终端...

    UNIX环境高级编程

    10.15 sigsetjmp 和siglongjmp函数 10.16 sigsuspend函数 10.17 abort函数 10.18 system 函数 10.19 sleep函数 10.20 作业控制信号 10.21 其他特征 10.21.1 信号名字 10.21.2 SVR4信号处理程序的附加参数 10.21.3 ...

    UNIX环境高级编程(第二版中文)

    10.15 sigsetjmp和siglongjmp函数 266 10.16 sigsuspend函数 268 10.17 abort函数 274 10.18 system函数 276 10.19 sleep函数 280 10.20 作业控制信号 282 10.21 其他特征 284 10.22 小结 285 习题...

    IT行业中必备技能之UNIX最佳学习资料

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    unix环境编程电子书

    261 10.15 sigsetjmp和siglongjmp函数 266 10.16 sigsuspend函数 268 10.17 abort函数 274 10.18 system函数 276 10.19 sleep函数 280 10.20 作业控制信号 282 10.21 其他特征 284 10.22 小结 285 ...

    UNIX环境高级编程和源代码

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    Unix高级编程 pdf

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21....

    UNIX环境高级编程(PDF)

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    UNIX环境高级编程(中文版+英文版+源代码)

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    UNIX环境高级编程.pdf

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    Unix环境高级编程电子书

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    中文第一版-UNIX环境高级编程

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    UNIX环境高级编程(第二版中文).pdf

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

    UNIX环境高级编程(第二版中文).

    10.15 sigsetjmp 和siglongjmp函数 226 10.16 sigsuspend函数 229 10.17 abort函数 234 10.18 system函数 235 10.19 sleep函数 240 10.20 作业控制信号 241 10.21 其他特征 243 10.21.1 信号名字 243 10.21.2 SVR4...

Global site tag (gtag.js) - Google Analytics