問題タブ [ucontext]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - ジェネリック関数ポインターを呼び出すためのsetcontextおよびmakecontext
別の質問で、コードを移植する際に問題が発生しました。
64ビットプラットフォームと多くの人に、32ビットと64ビットの呼び出し変換の違いと移植性の問題のために、代わりにsetcontext( )関数とmakecontext()関数を使用する必要があると言われました。
ええと、私は本当に有用なドキュメントをオンラインで見つけることができません、または少なくともこれを実装するために必要な種類ではないので、これらの関数を使用して引数をスタックにプッシュし、ジェネリック関数ポインターを呼び出し、戻り値を取得するにはどうすればよいですか?その後、レジスタを復元しますか?
c++ - makecontext()/swapcontext() 関数は C++ と互換性がありますか?
Unix 環境ではmakecontext()/swapcontext()
、C でコルーチンを実装するために関数ファミリーが使用されることがあります。ただし、これらの関数は、スタックと実行フローを直接操作します。多くの場合、C から C++ に切り替えると、これらの低レベルの機能がまったく異なります。
makecontext()
問題は、 andを使用してコルーチンを実装する際に問題があるかどうかswapcontext()
です。もちろん、例外がそのようなコルーチンを決してエスケープできないように、非常に細心の注意を払う必要があることは明らかです。これは、スタックに例外ハンドラーがなく、プログラムが segfault になる可能性が高いためです。しかし、それ以外に、C++ が内部で物事を処理する方法と実行パスmakecontext()
を変更する方法との間に互換性がないことはありますか?setcontext()
c - ucontextがPOSIXに追加された後、POSIXから削除されたのはなぜですか?
私の知る限り、ucontext
それよりも優れたものを提供していますsetjmp
。ただし、非推奨になり、POSIX仕様から削除されました。では、なぜそれが表示され、なぜ削除されたのでしょうか。
c - getcontext/setcontext でスタックを上下に切り替える
getcontext/setcontext が特定のシナリオで正しく機能するかどうかを理解しようとしています。
setcontext() を使用して、スタックを履歴の特定の場所に巻き戻す方法を確認できます。
しかし、巻き戻した後、未来の場所に巻き戻すことができるかどうか疑問に思っていましたか? これは、getcontext()
呼び出しがスタックのコピーをキャプチャすることに依存していると思いますが、ドキュメントで正確な詳細を見つけることができません。
c - SIGALRM によるスレッド コンテキストの切り替え
私は問題があります。タイマーと SIGALRM を使用して ucontext スレッドを切り替えるプログラムを実装する必要がありますが、evict_thread 関数を使用してスレッドを切り替えると、セグメンテーション エラーが発生します。プログラムの実行中にさまざまな時点で発生するため、競合状態の結果であると思います。これが私のevict_threadです
上記の関数は、次の方法で呼び出されます
実行キューは、ucontext スレッドへのポインターのグローバル テーブルへのインデックスである整数の単なるグローバル リストです。リストは、libslack.org で入手可能な C 汎用ユーティリティ ライブラリのリスト データ構造を使用して実装されます。
タイマーを無効にして、コンテキストを切り替える前に各スレッドを最後まで実行すると、プログラムは正常に実行されますが、実行中にスレッドが切り替えられると、約 80% の確率でセグメンテーション エラーが発生します。
また、gdb を使用してセグメンテーション違反をバックトレースしようとすると、システムコール内で発生したと表示されます。
c - SIG_INFO で sigaction ハンドラーの 3 番目のパラメーター (void* コンテキスト) を使用すると、セグメンテーション違反が発生します
問題を引き起こした巨大なファイバー スケジューラ コードを以下の行にまとめました。
私が期待しているのは、毎回ハンドラーに渡されたコンテキストへのクリーンなリターンです。
私が得るのは "Handler." で、3 回出力された後、セグメンテーション違反が発生します。
2 つの異なる Linux ディストリビューションで gcc-4.4.3 と gcc-4.4.5 の両方を使用しました。
c - Linux で EBP レジスタの内容を取得する
関数の戻りアドレスを取得するために EBP/RBP の内容が必要です。このアドレスは、スタック フレーム内の 8(%RBP) の位置にある必要があります (x86_64 ビット アーキテクチャのみを考えてみましょう)。
シグナル ハンドラに渡される ucontex_t 構造体からこの値を取得しますが、プログラムは非常に奇妙な動作をします。RBP レジスタに含まれる値がまったく意味をなさない場合 (たとえば、0x00、0x01) や、正しいスタック ベース値が含まれている場合があります。もちろん、この動作はいくつかのアプリケーションのクラッシュを引き起こします。
呼び出し元関数のアドレスを知りたいので、関数の戻りアドレスを取得する必要があります。
これは私が使用しているコードです:
マクロは次のように定義されます。
前のコードの出力の例: 正しい値:
間違った値:
さらに悪いことに:
RBP にゼロが含まれている場合、アプリケーションが終了するまで同じ値が保持されることに気付きました。