• 17、深入理解计算机系统笔记:非本地跳转


    1C提供了用户级异常控制流,称为非本地跳转(nonlocal jump),它将控制流从一个函数转移到另一个当前正在执行的函数;而不需要经过正常的调用-返回序列。通过setjmplongjmp来实现的。

    函数原形

    #include <setjmp.h>
    int setjmp(jmp buf env);
    int sigsetjmp(sigjmp buf env, int savesigs); //信号版本
    returns: 0 from setjmp, nonzero from longjmps)
    #include <setjmp.h>
    void longjmp(jmp buf env, int retval);
    void siglongjmp(sigjmp buf env, int retval); //信号版本
    never returns)
    

    C++提供的异常机制是高层次的,是Csetjmp,longjmp函数的更加结构化的版本。可把try语句中的catch子句看作是setjmp函数的类似物;throw语句类似于longjmp函数。

    The setjmp function saves the current stack context in the env buffer, for later

    use by longjmpThe longjmp function restores the stack context from the env buffer

    and then triggers a return from the most recent setjmp call that initialized env. The

    setjmp then returns with the nonzero return value retval.

    The setjmp function is called once but returns multiple times: once when the

    setjmp is first called and the stack context is stored in the env buffer, and once for

    each corresponding longjmp call. On the other hand, the longjmp function is called

    once but never returns

    2、应用

    1)允许从一个深层嵌套的函数调用中立即返回,通常是由检测到错误引起的。

    示例代码

    /* $begin setjmp */
    #include "csapp.h"
    
    jmp_buf buf;
    
    int error1 = 0; 
    int error2 = 1;
    
    void foo(void), bar(void);
    
    int main() 
    {
        int rc;
    
    	rc = setjmp(buf);
    /*The main routine first calls setjmp to save the current stack context*/
        if (rc == 0)
    	foo();
        else if (rc == 1) 
    	printf("Detected an error1 condition in foo\n");
        else if (rc == 2) 
    	printf("Detected an error2 condition in foo\n");
        else 
    	printf("Unknown error condition in foo\n");
        exit(0);
    }
    
    /* deeply nested function foo */
    void foo(void) 
    {
        if (error1)
    	longjmp(buf, 1); 
        bar();
    }
    
    void bar(void) 
    {
        if (error2)
    	longjmp(buf, 2); 
    }
    /* $end setjmp */
    

    2)使一个信号处理程序分支到一个特殊的代码位置,而不是返回到被信号到达中断了的位置。

    示例代码

    /* $begin restart */
    #include "csapp.h"
    
    sigjmp_buf buf;
    
    void handler(int sig) 
    {
        siglongjmp(buf, 1);
    }
    
    int main() 
    {
        Signal(SIGINT, handler);
    
    	if (!sigsetjmp(buf, 1)) 
    /*The initial call to the sigsetjmp function saves the stack and signal context when the program first starts.*/
    	printf("starting\n");
        else 
    	printf("restarting\n");
    
        while(1) {
    	Sleep(1);
    	printf("processing...\n");
        }
        exit(0);
    }
    /* $end restart */
    /*The program uses signals and nonlocal jumps to do a soft restart whenever the user types ctrl-c at the keyboard.当捕获到SIGINT信号时,不是从信号处理程序返回到被中断的处理循环,而是跳转到the beginning of the main program.*/
    

    <Computer Systems:A Programmer's Perspective>

  • 相关阅读:
    一款纯css3实现的响应式导航
    一款基于TweenMax.js的网页幻灯片
    4款基于jquery的列表图标动画切换特效
    随着鼠标移动的文字阴影
    一款纯css实现的垂直时间线效果
    一款基于jquery的侧边栏导航
    (转) 共享个很棒的vim配置
    [Leetcode] String to Integer (atoi)
    dia无法输入中文?
    [Leetcode] Sum Root to Leaf Numbers
  • 原文地址:https://www.cnblogs.com/mydomain/p/2084155.html
Copyright © 2020-2023  润新知