核心原始碼:do_fork()中的parent_tidptr和child_tidptr是什麼?

核心原始碼:do_fork()中的parent_tidptr和child_tidptr是什麼?

就上述關聯parent_tidptr創建新流程child_tidptr是什麼意思?do_fork()

答案1

讓我們先查看原始系統呼叫介面。它因體系結構而略有不同,但在 x86-64 上是:

   long clone(unsigned long flags, void *child_stack,
              int *ptid, int *ctid,
              unsigned long newtls);

ptidctid你的parent_tidptrchild_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. 

這些標誌主要是為了實現線程庫而設計的。如果我們看一下 NPTL 的實現pthread_create()在 glibc 內部,我們最終找到了程式碼sysdeps/unix/sysv/linux/createthread.cclone()進行包含CLONE_PARENT_SETTIDand CLONE_CHILD_CLEARTIDin 的呼叫flags

在該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 之間存在一一對應的關係。內核線程 ID 與您使用 Linux 獲得的 ID 相同gettid()稱呼。它也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_tidlll_futex_waitFUTEX_WAITCLONE_CHILD_CLEARTID

答案2

tid代表“線程 ID”。參數parent_tidptrchild_tidptr分別指向父進程位址空間和子進程位址空間中的使用者空間記憶體。新建立的線程的 id 儲存在指標指向的 int 變數中。

欲了解更多信息,請參閱clone(2)線上說明頁

相關內容