カーネル ソース コード: do_fork() の parent_tidptr と child_tidptr とは何ですか?

カーネル ソース コード: do_fork() の parent_tidptr と child_tidptr とは何ですか?

上記についてリンク新しいプロセスを作成するとparent_tidptrchild_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_SETTIDCLONE_CHILD_CLEARTIDflags

このclone()呼び出しでは、引数ptidctid引数が同じアドレスを指す(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クリアするために使用される理由は、ptidctidpthread_join()別のスレッドを呼び出して、スレッドが終了したかどうかを確認します。本質的には、ptid/のctid場所はフューテックス、 そしてそのfutex()システム コールは、この位置の整数が変化するのを待ってブロックするために使用されます。(詳細は少し複雑ですが、glibc ソース コードでのと のgrep使用についてです。最終的には、操作が行われます。上記で、ターゲット アドレスで futex ウェイクアップが実行されたことを思い出してください。)lll_wait_tidlll_futex_waitFUTEX_WAITCLONE_CHILD_CLEARTID

答え2

tidは「スレッド ID」を表します。パラメータparent_tidptrと は、child_tidptrそれぞれ親プロセス アドレス空間と子プロセス アドレス空間のユーザー空間メモリを指します。新しく作成されたスレッドの ID は、ポインタが指す int 変数に格納されます。

詳細については、clone(2)マニュアルページ

関連情報