美文网首页
setjmp 和 longjmp

setjmp 和 longjmp

作者: 给艺艺一个未来 | 来源:发表于2022-11-26 20:33 被阅读0次

    Linux manual page (手册):setjmplongjmp

    总览

    头文件
    setjmp.h

    函数

    int setjmp(jmp_buf env);
    noreturn void longjmp(jmp_buf env, int val);
    

    jmp_buf
    jmp_buf 类型是一种数组类型,适合存储恢复调用环境的信息(比如:函数栈-栈帧指针BP和栈顶指针SP,程序指针PC-未来恢复时Jump到的语句地址,其他寄存器信息-通用寄存器等)(不包括:浮点状态标志、打开的文件或任何其他数据的状态)。

    详见:setjmp.h

    描述

    背景
    goto 只能在函数内跳转,而不能在函数间跳转,因此 C 语言引入 setjmp 和 longjmp 。

    用法
    setjmp 使用 jmp_buf 保存当前函数的调用信息,longjmp 使用一个存有函数调用信息的 jmp_buf 跳转到另一个函数并恢复调用。

    setjmp

    参数:env 为保存函数调用环境信息的 jmp_buf 对象。

    返回值:

    • 0 :表示 jmp_buf 的 setjmp 时的返回值。
    • 非零:表示 jmp_buf 的 longjmp 时的返回值(jmp_buf 的 longjmp会再次从 jmp_buf
      的 setjmp处返回),返回值由 longjmp 中的参数 val 指定。详见:longjmp 。

    longjmp
    参数:env 为另一函数调用环境信息的 jmp_buf 对象,val 为 longjmp 回到 jmp_buf 所存函数的 setjmp 调用处的返回值。

    返回值:无返回值,从 jmp_buf 指向的函数中的 setjmp 调用处返回。

    上下文切换

    context_switch

    吐槽一句:简书的markdown不好用耶,有办法让下面的代码块能更好看些吗?

    #define context_switch(coroutine_a, coroutine_b)                                \
      if (setjmp(coroutine_a->jmp_buf) == 0) {                                      \
          /*                                                                        \
           * setjmp save coroutine a jmp_buf success                                \
           * use longjmp goto coroutine b jmp_buf setjmp and return 1               \
           */                                                                       \
          longjmp(coroutine_b->jmp_buf, 1)                                          \
      }                                                                             \
      /* setjmp is not 0, so return from longjmp, then coroutine b run continue */  \
    

    示例

    #include <setjmp.h>
    
    jmp_buf context_main, context_a, context_b;
    
    void pirnt_a();
    void print_b();
    
    void main()
    {
        if (setjmp(context_main)==0) {
            print_a();
        } else {
            printf("2.return main\n");
       }
    
        if (setjmp(context_main)==0) {
            print_b();
        } else {
            printf("6.return main\n");
            printf("7.return b from main\n");
            longjmp(context_main, 1);
        }
       
    }
    
    void print_a() 
    {
        if (setjmp(context_a)==0) {
            printf("1.return main from a\n");
            longjmp(context_main, 1);
        } else {
            printf("4.return a\n");
            printf("5.return main from a\n");
            longjmp(context_b, 1);
       }
    }
    
    void print_b() 
    {
        if (setjmp(context_a)==0) {
            printf("3.return a from b\n");
            longjmp(context_a, 1);
        } else {
            printf("8.return b\n");
       }
    }
    

    相关文章

      网友评论

          本文标题:setjmp 和 longjmp

          本文链接:https://www.haomeiwen.com/subject/hrrnnrtx.html