2013-02-27 45 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