Jmp_buf構造体の各エントリは何を保持しますか?
質問
Ubuntu 9.10(Karmic Koala)を実行しています。12個のintの配列であるjmp_buf
構造を調べました。 setjmp
を使用して、<=>構造を渡すと、<!>#8212; 12個のエントリのうち4個が保存されます。これらの4つのエントリは、スタックポインター、フレームポインター、プログラムカウンター、およびリターンアドレスです。他の8つのエントリは何のためですか?それらはマシン依存ですか?別のエントリはセグメントテーブルベースレジスタですか?スレッド/プロセスの環境を適切に復元するには、他に何が必要ですか?マニュアルページやその他のソースを調べましたが、<=>のアセンブリコードが見つかりませんでした。
解決
MacOS X 10.6.2では、ヘッダー<setjmp.h>
は最終的に<i386/setjmp.h>
を使用し、そこに次のように表示されます。
#if defined(__x86_64__)
/*
* _JBLEN is number of ints required to save the following:
* rflags, rip, rbp, rsp, rbx, r12, r13, r14, r15... these are 8 bytes each
* mxcsr, fp control word, sigmask... these are 4 bytes each
* add 16 ints for future expansion needs...
*/
#define _JBLEN ((9 * 2) + 3 + 16)
typedef int jmp_buf[_JBLEN];
typedef int sigjmp_buf[_JBLEN + 1];
#else
/*
* _JBLEN is number of ints required to save the following:
* eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags, eip,
* cs, de, es, fs, gs == 16 ints
* onstack, mask = 2 ints
*/
#define _JBLEN (18)
typedef int jmp_buf[_JBLEN];
typedef int sigjmp_buf[_JBLEN + 1];
#endif
Linuxでも同様の要件があります。jmp_buf
には、必要な状態を保存するのに十分な情報が含まれています。そして、それを使用するために、何が含まれているかを本当に知る必要はありません。あなたがする必要があるのは、実装者がそれを正しく取得したという信頼だけです。実装を変更する場合は、もちろん理解する必要があります。
setjmpとlongjmpは非常にマシン固有であることに注意してください。 Plaugerの<!> quot; 標準Cライブラリ <!> quot;それらの実装に関係する問題のいくつかの議論のため。最新のチップでは、本当にうまく実装するのが難しくなります。
他のヒント
setjmp
/ longjmp
/ sigsetjmp
は、CPUアーキテクチャ、オペレーティングシステム、およびスレッドモデルに大きく依存しています。最初の2つの関数は、有名な(または悪名高い<!>#8212; POVに応じて)オリジナルのUnixカーネルでは<!> quot; structured <!> quot;として登場しました。 I / Oエラーやその他の厄介な状況から、失敗したシステムコールを解く方法。
/usr/include/setjmp.h(Linux Fedora)の構造のコメントには、呼び出し環境と、場合によっては保存されたシグナルマスクが含まれています。 /usr/include/bits/setjmp.hが含まれています明らかにx86ファミリに固有の6つの32ビット整数の配列を持つようにjmp_bufを宣言します。
PPC実装、そこにあるコメントは、FPU設定を保存する必要があることを合理的に示唆しています。丸めモード、デフォルトのオペランドサイズ、例外処理などの復元に失敗すると驚くことになります。
このような構造で実際に必要なスペースよりも少し多くスペースを確保するのは、システムエンジニアの典型です。いくつかの余分なバイトは、特に<=> / <=>の実際の使用の希少性を考慮すると、ほとんど汗をかくことはありません。スペースが少なすぎることは間違いなく危険です。私が考えることができる最も顕著な理由は、余分な<!>#8212; <!>#8212にスポットがあるのではなく、ランタイムライブラリのバージョンが変更されてjmp_bufでより多くのスペースが必要になった場合です予約されているため、それを参照するプログラムを再コンパイルする必要はありません。