baw*_*nal 6 kernel system-calls linux-kernel
在上述链接何谓parent_tidptr
并child_tidptr
在do_fork()
其中创建新的进程?
让我们从原始系统调用接口开始。它因架构而异,但在 x86-64 上是:
long clone(unsigned long flags, void *child_stack,
int *ptid, int *ctid,
unsigned long newtls);
Run Code Online (Sandbox Code Playgroud)
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.
Run Code Online (Sandbox Code Playgroud)
这些标志主要用于实现线程库。如果我们查看pthread_create()
glibc 内部的 NPTL 实现,我们最终会发现其中的代码sysdeps/unix/sysv/linux/createthread.c
进行了clone()
包含CLONE_PARENT_SETTID
和CLONE_CHILD_CLEARTID
in的调用flags
。
在那个clone()
调用中,我们还可以看到ptid
和ctid
参数指向相同的地址。(请记住,POSIX 线程共享一个地址空间;这是通过clone()
CLONE_VM
标志实现的。)
所以,这里发生的事情如下。
CLONE_PARENT_SETTID
用于确保内核线程 ID 存储在用户空间中的某个位置。线程实现的用户空间端需要知道该线程 ID。CLONE_CHILD_CLEARTID
当创建的线程clone()
终止时,用于清除(即,零)相同的位置。让我们走得更远一点......
经由返回的线程ID ptid
/ctid
是不相同的,为POSIX线程ID( pthread_t
),虽然在1:1的线程实现,例如NPTL,有内核线程ID和POSIX线程ID之间的一对一的对应关系。内核线程 ID 与您使用 Linuxgettid()
调用获得的 ID 相同。它也clone()
作为系统调用返回值返回,这就提示了一个问题:为什么我们需要ptid
/ ctid
?问题是,从用户空间方面来看,事情是这样的:
tid = clone(...);
Run Code Online (Sandbox Code Playgroud)
从用户空间线程实现的角度来看,这里存在竞争,因为分配 totid
仅在 clone()
返回后发生。这意味着如果用户空间线程库在新线程执行任何操作(例如终止)之前需要该信息,则它可能会遇到某些问题。UsingCLONE_PARENT_SETTID
确保新线程 ID 放置在返回ptid
之前
指向的位置clone()
,从而允许线程库避免这种竞争条件。(CLONE_CHILD_SETTID
也可以用于类似的效果。)
CLONE_CHILD_CLEARTID
用于清除ptid
/的原因是ctid
为pthread_join()
另一个线程中的调用提供一种方法来发现该线程已终止。本质上,ptid
/ctid
位置是作为futex使用的,futex()
系统调用是用来阻塞的,等待这个位置的整数改变。(细节有点复杂,但grep
对于glibc 源代码中的lll_wait_tid
和 的使用lll_futex_wait
。最终,发生了一个FUTEX_WAIT
操作。回想一下,CLONE_CHILD_CLEARTID
上面对目标地址进行了 futex 唤醒。)
tid
代表“线程 ID”。参数parent_tidptr
和child_tidptr
分别指向父进程地址空间和子进程地址空间中的用户空间内存。新创建的线程的 id 存储在指针指向的 int 变量中。
有关详细信息,请参阅clone(2)
联机帮助页。