私は現在、 clone() を使用してスレッド化を実装するつもりです。質問は、すべてのスレッドが同じメモリ空間を使用している場合、特定のスレッドで呼び出す各関数で、同じ関数がまたは、これが確実に行われるようにするために何かをする必要がありますか?
1 に答える
各スレッドは全体的に同じメモリ マップを使用しますが、関数呼び出し用に別の個別のスレッド ローカル スタックを使用します。異なるスレッドが同じ関数 (それ自体は同じ実行可能メモリの場所にある) を呼び出した場合、ローカル変数は共有されません。これは、関数へのエントリ時に / 必要に応じてスタックに割り当てられ、各スレッドが独自のデフォルトでスタックします。
mmap
静的/グローバル メモリへの参照 (つまり、スレッド ローカル スタックに割り当てられていないもの。たとえば、グローバルや、呼び出し後にスレッドに渡された/スレッドに表示されるヒープまたはメモリ領域への参照clone
、および一般に、完全なメモリ マップともちろん、プロセス コンテキスト自体) は共有され、通常のマルチスレッドの問題 (つまり、共有状態の同期) の影響を受けます。
を呼び出す前に、このスレッド ローカル スタック スペースを自分でセットアップする必要があることに注意してくださいclone
。マンページから:
child_stack
引数は、子プロセスが使用するスタックの場所を指定します。子プロセスと呼び出しプロセスはメモリを共有する可能性があるため、子プロセスを呼び出しプロセスと同じスタックで実行することはできません。したがって、呼び出しプロセスは、子スタックのメモリ空間を設定し、この空間へのポインタを に渡す必要がありますclone()
。スタックは、Linux を実行するすべてのプロセッサ (HP PA プロセッサを除く) で下向きに成長するためchild_stack
、通常、子スタック用に設定されたメモリ空間の最上位アドレスを指します。
パラメータはのchild_stack
2 番目の引数clone
です。を介して作成された各子スレッドがclone
、そのスタック用に個別の重複しないメモリ チャンクを確実に受け取るのは、呼び出し元 (つまり、親スレッド) の責任です。
このスレッド ローカル スタック メモリ領域の割り当てと設定は、まったく単純ではないことに注意してください。割り当てがページ アラインされていること (開始アドレスが 4K 境界上にある)、ページ サイズの倍数 (4K)、十分なサイズ (スレッドが数個しかない場合は 2MB が安全)、理想的には "使用可能なスペースに続く「ガード」セクション。スタック ガードは、メイン スタック領域に続く、アクセス権限のない (読み取りも書き込みもできない) ページの数であり、スレッドが動的にそのスタック サイズを超えた場合に仮想メモリ アドレス空間の残りを保護します (たとえば、束ローカル変数として非常に大きな一時バッファーを持つ再帰または関数の) スタック ガード領域に成長し続けようとします。スタック ガードは技術的にはオプションです。あなたはおそらく使用しているはずですmmap
スタックを割り当てるposix_memalign
こともできますが、同様に行います。
そうは言っても、私は尋ねなければなりません: なぜ最初にスレッド化を実装しようとするのclone
ですか? ここにはいくつかの非常に困難な問題があり、POSIX スレッド ライブラリはそれらを解決しました (同様に移植可能な方法で)。clone
それがあなたが望むきめ細かな制御である場合は、pthread_attr_*
関数をチェックアウトしてください。それらは、あいまいではないすべてのユースケースをほとんどカバーしています(たとえば、必要に応じて独自のスタックを割り当てることができます。前の説明から、そうしないと思います)。非常にパフォーマンスの高い一般的な Linux 実装は、とりわけ、clone
スレッド化に関連するさまざまな他の凶悪なシステム コールを完全にラップし、それらの多くは C ライブラリ ラッパーさえ持っておらず、 経由で呼び出す必要がありますsyscall
。それはすべて、あなたが何をしたいかによって異なります。