6

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

1 に答える 1

4

getcontextスタックをコピーせず、レジスタ(スタックポインタを含む)とシグナルマスクなどの小さなコンテキストデータのみをダンプします。

スタックをジャンプダウンすると、トップコンテキストが無効になります。関数呼び出しを行わない場合でも、そこで実行できるシグナルハンドラーについて考えてください。2つのスタック間をジャンプする場合は、次のようにする必要があります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
于 2013-02-28T02:48:01.343 に答える