Neither fork()
nor vfork()
keep the same PID although clone()
can in one scenario (*a). They are all different ways to achieve roughly the same end, the creation of a distinct child.
clone()
is like fork()
but there are many things shared by the two processes and this is often used to enable threading.
vfork()
is a variant of clone
in which the parent is halted until the child process exits or executes another program. It's more efficient in those cases since it doesn't involve copying page tables and such. Basically, everything is shared between the two processes for as long as it takes the child to load another program.
Contrast that last option with the normal copy-on-write where memory itself is shared (until one of the processes writes to it) but the page tables that reference that memory are copied. In other words, vfork()
is even more efficient than copy-on-write, at least for the fork-followed-by-immediate-exec use case.
But, in most cases, the child has a different process ID to the parent.
*a Things become tricky when you clone()
with CLONE_THREAD
. At that stage, the processes still have different identifiers but what constitutes the PID begins to blur. At the deepest level, the Linux scheduler doesn't care about processes, it schedules threads.
A thread has a thread ID (TID) and a thread group ID (TGID). The TGID is what you get from getpid()
.
When a thread is cloned without CLONE_THREAD
, it's given a new TID and it also has its TGID set to that value (i.e., a brand new PID).
With CLONE_THREAD
, it's given a new TID but the TGID (hence the reported process ID) remains the same as the parent so they really have the same PID. However, they can distinguish themselves by getting the TID from gettid()
.
There's quite a bit of trickery going on there with regard to parent process IDs and delivery of signals (both to the threads within a group and the SIGCHLD
to the parent), all which can be examined from the clone()
man page.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…