/* $begin restart */
#include "csapp.h"
sigjmp_buf buf;
void handler(int sig)
{
siglongjmp(buf, 1);
}
int main()
{
Signal(SIGINT, handler);
if (!sigsetjmp(buf, 1))
printf("starting\n");
else
printf("restarting\n");
while(1) {
Sleep(1);
printf("processing...\n");
}
exit(0);
}
/* $end restart */
setjmp函数
#include <setjmp.h>
int setjmp(jmp_buf env);
int sigsetjmp(sigjmp_buf env, int savesigs);
setjmp函数在env缓冲区中保存当前调用环境,以供后面的longjmp使用,并返回0。调用环境包括程序计数器、栈指针和通用目的寄存器。
longjmp函数
#include <setjmp.h>
void longjmp(jmp_buf env, int val);
void siglongjmp(sigjmp_buf env, int val);
longjmp函数从env缓冲区中恢复调用环境,然后触发一个从最近一次初始化env的setjmp调用的返回。
核心要点:
setjmp函数之被调用一次,但返回多次,一次是当第一次调用setjmp,而调用环境保存在缓冲区env中时;一次是为每个相应的longjmp调用。
longjmp函数被调用一次,但从不返回。
非本地返回的意义:
非本地返回的一个重要意义在于允许从一个深层嵌套的函数中立即返回,而不用费力解开调用栈。
例程分析:
setjmp在第一次被调用的时候返回0 ,打印出”starting“
之后如果按下ctrl+c就会发送SIGINT信号,进程接收到该信号后就会调用信号处理程序,信号处理程序执行longjmp,触发setjmp返回,返回值为val,即为1,则进程打印输出restarting。之后继续跳入while循环。