2013-02-27 46 views
6

我想了解getcontext/setcontext是否可以在特定场景中正常工作。使用getcontext/setcontext切换堆栈/向下堆栈

我可以看到如何使用setcontext()将堆栈展开回历史中的某个位置。

#include <stdio.h> 
#include <ucontext.h> 

int rollback = 0; 
ucontext_t context; 

void func(void) 
{ 
    setcontext(cp); 
} 

int main(void) 
{ 
    getcontext(&context); 
    if (rollback == 0) 
    { 
     printf("getcontext has been called\n"); 
     rollback++; 
     func(); 
    } 
    else 
    { 
     printf("setcontext has been called\n"); 
    } 
} 

但是我想知道如果放松后你能重新回到未来的地方吗?我想这取决于getcontext()调用捕获堆栈的副本,​​我无法在文档中找到确切的详细信息。

#include <stdio.h> 
#include <ucontext.h> 

int rollback  = 0; 
int backToFuture = 0; 
ucontext_t context; 
ucontext_t futureContext; 

void func(void) 
{ 
    // Some complex calc 
    if (some-condition) 
    { 
     getcontext(&futureContext); // After returning I want to come back 
            // here to carry on with my work. 
     if (backToFuture == 0) 
     { 
      setcontext(&context); // rewind to get stuff-done 
     } 
    } 
    // Finishe work 
} 

int main(void) 
{ 
    getcontext(&context); 
    if (rollback == 0) 
    { 
     printf("getcontext has been called\n"); 
     rollback++; 
     func(); 

     // eventually always return here. 
    } 
    else 
    { 
     printf("setcontext has been called\n"); 
     // Do specialized work that needed to be done 
     // May involve function calls. 
     // 
     // I worry that anything the adds new stack frames 
     // will disrupt the saved state of futureContext 
     // 
     // But without detailed information I can not be sure 
     // if this is an allowed senario. 
     backToFuture = 1; 
     setcontext(&futureContext); 
    } 
} 

回答

4

getcontext不复制栈,当你跳下它无效顶部上下文堆栈它只转储寄存器(包括堆栈指针)和类似的信号掩模一点上下文数据等

。即使你不会做任何函数调用,也要考虑可以在那里执行的信号处理程序。如果你想在两个堆栈之间跳转,你需要makecontext

我添加变量,以证明你的代码是无效的:

void func(void) 
{ 
    // Some complex calc 
    if (1) 
    { 
     volatile int neverChange = 1; 
     getcontext(&futureContext); // After returning I want to come back 
            // here to carry on with my work. 
     printf("neverchange = %d\n", neverChange); 
     if (backToFuture == 0) 
     { 
      setcontext(&context); // rewind to get stuff-done 
     } 
    } 
    // Finishe work 
} 

在我的机器它会导致:

getcontext has been called 
neverchange = 1 
setcontext has been called 
neverchange = 32767 
+0

可以使用您提供的代码在您的文章的正确版本'makecontext '?确切地说,我想在信号处理程序中创建一个函数调用(应该在处理程序返回后执行)。如果我抛出这个新创建的函数并尝试/捕获外部原始上下文,我还希望堆栈展开(throw/catch)正常工作。这需要创建一个动态函数调用(堆栈框架创建),我假设。我不确定是否可以使用setcontext(ucontext_t中的uc_link?)。 – Etherealone 2016-09-19 13:28:25

+0

我设法在这个新创建的函数调用上使用makecontext,但是在执行新函数调用后,将uc_link设置为signal_handler的最后一个参数(ucontext_t)没有正确返回到旧的上下文。 (P.S.在我之前的评论中,堆栈展开的目的是我想干净地中止一个造成非灾难性信号的违规操作)。 – Etherealone 2016-09-19 13:35:01

+0

@Elehereone,我认为这对于这个评论主题来说太复杂了,但是如果你创建一个,请随时将我链接到一个问题。 – zch 2016-09-19 14:42:09