%20%E3%81%AE%20parent_tidptr%20%E3%81%A8%20child_tidptr%20%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%A7%E3%81%99%E3%81%8B%3F.png)
上記についてリンク新しいプロセスを作成するとparent_tidptr
とchild_tidptr
はどういう意味ですか?do_fork()
答え1
まず、生のシステム コール インターフェイスを見てみましょう。アーキテクチャによって多少異なりますが、x86-64 では次のとおりです。
long clone(unsigned long flags, void *child_stack,
int *ptid, int *ctid,
unsigned long newtls);
ptid
と はctid
あなたparent_tidptr
の とですchild_tidptr
。では、clone(2)
マニュアルページには次のように書かれています:
CLONE_CHILD_CLEARTID (since Linux 2.5.49)
Erase the child thread ID at the location ctid in
child memory when the child exits, and do a wakeup on
the futex at that address.
CLONE_CHILD_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ctid in the
child's memory.
CLONE_PARENT_SETTID (since Linux 2.5.49)
Store the child thread ID at the location ptid in the
parent's memory.
これらのフラグは主にスレッドライブラリを実装するために設計されました。pthread_create()
glibcの内部では、最終的に次のようなコードが見つかりますsysdeps/unix/sysv/linux/createthread.c
およびをclone()
含む呼び出しを実行します。CLONE_PARENT_SETTID
CLONE_CHILD_CLEARTID
flags
このclone()
呼び出しでは、引数ptid
とctid
引数が同じアドレスを指す(POSIX スレッドはアドレス空間を共有することに注意してください。これはフラグによって実現されますclone()
CLONE_VM
。)
それで、ここで何が起こっているかというと、次のようになります。
CLONE_PARENT_SETTID
カーネル スレッド ID がユーザー空間の特定の場所に格納されていることを確認するために使用されます。スレッド実装のユーザー空間側では、そのスレッド ID を認識する必要があります。CLONE_CHILD_CLEARTID
によって作成されたスレッドがclone()
終了するときに、同じ場所をクリア (つまり、ゼロに) するために使用されます。
もう少し先へ進みましょう...
ptid
/経由で返されるスレッドIDctid
はないPOSIXスレッドID(pthread_t
)と同じですが、NPTLなどの1:1スレッド実装では、カーネルスレッドIDとPOSIXスレッドIDの間に1対1の対応があります。カーネルスレッドIDは、Linuxgettid()
呼び出します。これはclone()
システム コールの戻り値としても返されるため、なぜptid
/ が必要なのかという疑問が生じますctid
。問題は、ユーザー空間側から見ると、次のようになることです。
tid = clone(...);
ユーザー空間のスレッド実装の観点から見ると、ここでは競合が発生しています。なぜならtid
、後 clone()
が返します。これは、新しいスレッドが何かを行う前に(たとえば終了するなど)その情報が必要な場合、ユーザー空間スレッドライブラリが特定の問題に遭遇する可能性があることを意味します。を使用すると、CLONE_PARENT_SETTID
新しいスレッドIDがptid
前に
clone()
戻り値により、スレッド ライブラリはこのような競合状態を回避できます。 (CLONE_CHILD_SETTID
も同様の効果で使用できます。)
/をCLONE_CHILD_CLEARTID
クリアするために使用される理由は、ptid
ctid
pthread_join()
別のスレッドを呼び出して、スレッドが終了したかどうかを確認します。本質的には、ptid
/のctid
場所はフューテックス、 そしてそのfutex()
システム コールは、この位置の整数が変化するのを待ってブロックするために使用されます。(詳細は少し複雑ですが、glibc ソース コードでのと のgrep
使用についてです。最終的には、操作が行われます。上記で、ターゲット アドレスで futex ウェイクアップが実行されたことを思い出してください。)lll_wait_tid
lll_futex_wait
FUTEX_WAIT
CLONE_CHILD_CLEARTID
答え2
tid
は「スレッド ID」を表します。パラメータparent_tidptr
と は、child_tidptr
それぞれ親プロセス アドレス空間と子プロセス アドレス空間のユーザー空間メモリを指します。新しく作成されたスレッドの ID は、ポインタが指す int 変数に格納されます。
詳細については、clone(2)
マニュアルページ。