setjmp 和 longjmp

2022-11-26  本文已影响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 对象。

返回值:

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");
   }
}
上一篇 下一篇

猜你喜欢

热点阅读