内核源代码: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)联机帮助页

相关内容