マルチスレッドのプログラミング

スタックについて

通常、スレッドスタックはページ境界で始まります。指定したサイズはいずれも次のページ境界まで切り上げられます。アクセス権のないページはスタックのオーバーフローの最後に付加されます。このため、ほとんどのスタックオーバーフローで、違反したスレッドに SIGSEGV シグナルが送られるようになります。呼び出し側で割り当てられたスレッドスタックは、そのまま使用されます。

スタックを指定するときは、スレッドを PTHREAD_CREATE_JOINABLE として生成する必要があります。このスタックは、そのスレッドに対する pthread_join(3C) 呼び出しが終了まで解放できません。これは、スレッドが終了するまで、そのスレッドのスタックを解放できないからです。こうしたスレッドが確実に終了したことを確認するには、pthread_join(3C) を使用します。

スレッドへのスタック空間の割り当て

通常、スレッドにスタック空間を割り当てる必要はありません。システムは、各スレッドのスタックに対して、1M バイト (32 ビットシステムの場合) または 2M バイト (64 ビットシステムの場合) の仮想メモリーを割り当てます。スワップ空間は予約されません。システムは、mmap()MAP_NORESERVE オプションを使って割り当てを行います。

システムによって生成されたスレッドスタックは、それぞれレッドゾーンを持っています。システムはレッドゾーンとして、スタックオーバーフローを捕捉するためのページをスタックのオーバーフローの最後に付加します。このページは無効で、アクセスされるとメモリーフォルトになります。レッドゾーンは、自動的に割り当てられるすべてのスタックに付加されます。これは、そのサイズがアプリケーションで指定されたかデフォルトのサイズであるかに関係なく行われます。


注 –

実行時のスタック要件はライブラリ呼び出しや動的リンクによって異なります。したがって、指定したスタックがライブラリの呼び出しと動的リンクに必要な実行時要件を確実に満たすようにしなければなりません。


スタックとスタックサイズの一方または両方を指定するのが適正である場合はまれです。専門家であっても、適切なサイズを指定したかどうかを判断するのは困難です。ABI 準拠のプログラムでも、スタックサイズを静的に判定することはできません。スタックサイズは、プログラムが実行される、それぞれの実行環境に左右されます。

独自のスタックを構築する

スレッドスタックのサイズを指定するときは、呼び出される関数に必要な割り当てを計算してください。これには、呼び出し手続きで必要とされる量、局所変数、情報構造体が含まれます。

デフォルトスタックと少し違うスタックが必要になることがあります。たとえば、スレッドでデフォルトスタックサイズを超えるスタック空間が必要になる場合です。また、少しわかりにくいケースですが、デフォルトスタックが大きすぎる場合もあります。何千ものスレッドを生成する場合、デフォルトスタックでは合計サイズが数 G バイトにもなるため、仮想メモリーが足りず、それだけのスタック空間を扱えない可能性があります。

スタックサイズの上限は明らかであることが多いのですが、下限はどうでしょうか。スタックにプッシュされるスタックフレームを、その局所変数などを含めて、すべて扱えるだけのスタック空間が必要です。

スタックサイズの絶対最小値を取得するには、マクロ PTHREAD_STACK_MIN を呼び出します。マクロ PTHREAD_STACK_MIN は、NULL 手続きを実行するスレッドに必要な量のスタック空間を返します。実用的なスレッドに必要なスタック空間は最小スタックサイズより大きいので、スタックサイズを小さくするときは十分注意してください。