私は Ubuntu 9.10 (Karmic Koala) を実行していjmp_buf
ます。単純に 12 個の int の配列である構造を調べました。を使用setjmp
して構造体を渡すと、jmp_buf
12 個のエントリのうち 4 個が保存されます。これらの 4 つのエントリは、スタック ポインタ、フレーム ポインタ、プログラム カウンタ、およびリターン アドレスです。残りの 8 つのエントリは何ですか? それらはマシンに依存していますか? 別のエントリはセグメント テーブルのベース レジスタですか? スレッド/プロセスの環境を適切に復元するには、他に何が必要ですか? man ページやその他の情報源を調べましたが、 のアセンブリ コードが見つかりませんでしたsetjmp
。
2 に答える
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 の " The Standard C Library " を読んで、それらの実装に関するいくつかの問題について議論してください。最新のチップほど、うまく実装するのが難しくなります。
setjmp
// CPU アーキテクチャ、オペレーティング システム、longjmp
およびsigsetjmp
スレッド モデルに大きく依存します。最初の 2 つの関数は、元の Unix カーネルでは、I/O エラーやその他の厄介な状況など、失敗したシステム コールから巻き戻すための「構造化された」方法として有名でした (または悪名高く、POV によって異なります)。
/usr/include/setjmp.h (Linux Fedora) 内の構造体のコメントには、Calling environment と保存されたシグナル マスクが含まれている可能性があります。 /usr/include/bits/setjmp.h をインクルードして、明らかに x86 ファミリに固有の 6 つの 32 ビット整数の配列を持つように jmp_buf を宣言します。
PPC 実装以外のソースは見つかりませんでしたが、そこにあるコメントは、FPU 設定を保存する必要があることを合理的に示唆しています。丸めモード、デフォルトのオペランド サイズ、例外処理などの復元に失敗すると驚くことになるので、これは理にかなっています。
システム エンジニアは、このような構造で実際に必要なスペースよりも少し多くのスペースを確保するのが一般的です。setjmp
数バイトの追加は、特に/の実際の使用の希少性を考えると、ほとんど気にする必要はありませんlongjmp
。スペースが少なすぎることは間違いなく危険です。私が考えることができる最も顕著な理由は、余分なスペースが既に予約されていることにより、jmp_buf でより多くのスペースが必要になるようにランタイム ライブラリのバージョンが変更された場合、余分なスペースを確保することで、余分なスペースを確保することです。それ。