【问题标题】:problem with setjmp and longjmp to switch between 2 functionssetjmp 和 longjmp 在 2 个函数之间切换的问题
【发布时间】:2020-03-10 17:51:26
【问题描述】:

我正在尝试实现一个代码,该代码在函数 fun() 和 main() 之间不断切换,除了在屏幕上无限打印之外什么都不做。我正在尝试通过 setjmp 和 longjmp 切换并在 C 中使用 SIGALRM 信号。 但是当我运行它时,它只会运行一次,然后不会切换。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>

jmp_buf b1, b2;
int cur = 0;

void handlesig(int sig) {
    if(!cur) {
        cur = 1;
        setjmp(b2);
        longjmp(b1, 1);
    }
    else {
        cur = 0;
        setjmp(b1);
        longjmp(b2, 1);
    }
}

void fun() {    
    while(1) {
        printf("I am in function fun()\n");
        for(int x = 0; x < 100000000; x++);
    }
}

int main() {    
    signal(SIGALRM, handlesig);
    ualarm(900000, 900000);                     //send SIGALRM after each 900000 microseconds
    if(!setjmp(b1))
        fun();                                  //will be run when setjmp returns 0
    while(1) {                      
        printf("I am in function main()\n");    //will be run when setjmp returns 1
        for(int x = 0; x < 100000000; x++);
    }
    return 0;
}

我不明白这段代码有什么问题。

【问题讨论】:

  • 您是否尝试在调试器中运行它?
  • @JoelFan:这只会产生一堆损坏的帧。
  • 在这种情况下添加更多的 printf 语句。
  • 您确定没有优化粗略的“延迟”循环吗?
  • 我用printf查看handler函数是否被定期调用,发现它只被调用一次。

标签: c setjmp


【解决方案1】:

您的程序具有未定义的行为,因为在信号处理程序中在 b1b2 上调用 setjmp 的块的生命周期在调用 longjmp 时立即结束(在下一行)。下次您调用 longjmp 尝试返回不再有效的 jmp_buf 时,行为未定义,这表现为状态完全损坏。

您可以编写 a hack 来解决此问题,方法是使用sigaltstackSA_ONSTACK 标志让信号处理程序拥有多个堆栈,这样即使jmp_buf 正式无效,它实际上并没有被破坏。但这不是一个有效的程序,只是一个恰好在实践中在某些系统上(不是全部)工作的程序。最终,没有(有效/可靠的)方法可以使用setjmplongjmp 来满足您的要求;上下文切换需要一个比它们提供的严格更强的原语。

【讨论】:

猜你喜欢
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多