Linux Process Creation: fork, vfork, execv, clone

 

fork():

  • Makes a Duplicate of the current process, Identical in almost every way.
  • New process (child) gets a Different Process ID (PID) and PID of the old process (parent) as its Parent PID (PPID).
  • Two processes are now running exactly the same code.
  • Child and Parent Processes use different Virtual Address spaces, which is initially populated by the same memory pages.

Copy-On-Write:

  • As both processes are executed, the Virtual Address spaces begin to differ more and more, because the operating system performs a lazy copying of memory pages that are being written by either of these two processes and assigns an independent copies of the modified pages of memory for each process. This technique is called Copy-On-Write (COW).
  • Return value of fork()
    • Child process gets 0 in return.
    • Parent gets the new PID of the child in return.

vfork():

  • Basic difference between vfork() and fork() is that when a new process is created with vfork():
    • the Parent Process is Temporarily Suspended.
    • the Child Process might borrow the Parent's Address Space.
  • Child and Parent processes share the same Virtual Address Space, i.e. Parent and Child use the same Stack, Stack Pointer, Instruction Pointer.
  • As Virtual Address Space is shared between Parent and Child, to prevent unwanted interference the Parent Process is Frozen/Suspended, until:
    • the Child Process will call either exec() (create a new virtual address space and transition to a different stack)
    • or _exit() (termination of the process execution).
  • When Child Process either exit(), or calls execve(), then Parent Process Continues.
  • :warning: Child Process of a vfork() must be careful to Avoid Unexpectedly Modifying Variables of the Parent Process.
  • :warning: Child Process Must Not call exit(), if it needs to exit, it should use _exit();
    • because with vfork() child is potentially borrowing its Parent’s Address Space.
    • Anything vfork() does, besides calling execve() or _exit(), has a great potential to mess up the parent.
    • In particular, exit() calls atexit() handlers and other “finalizers”, e.g: it flushes std I/O streams.
  • :warning: Child Process Must Not Return from the function containing the vfork() call.
    • Returning from a vfork() Child would potentially (same caveat as before) mess the Parent's Stack.

use-case for vfork()

  • The vfork() function can be used to create new processes without fully copying the address space of the old process.
  • If a forked process is simply going to call exec, the data space copied from the parent to the child by fork() is not used.
  • This is particularly inefficient in a paged environment, making vfork() particularly useful. Depending upon the size of the parent's data space, vfork() can give a significant performance improvement over fork().

execv():

  • Replaces the entire Current Process with a New Program.
  • exec() replaces the Current Process with a the executable pointed by the function.
  • Control never returns to the original program unless there is an *exec() *error.
  • This system call with fork() system call together form a classical UNIX process management model called fork-and-exec.

clone(fn(arg)):

  • clone(), as fork(), creates a new process.
  • Unlike fork(), clone() allow the Child Process to share parts of its execution context with the calling process:
    • such as the Memory Space, the table of File Descriptors, and the table of Signal Handlers.
    • The Difference between fork() and clone() is which data structures (Memory Space, Processor State, Stack, PID, Open Files, etc) are shared or not.
  • Child Process is created with clone(), executes the function application fn(arg).
    • This differs from fork, where execution continues in the child from the point of the original fork call.
  • The fn argument is a Pointer to a Function that is called by the Child Process at the beginning of its execution.
  • The arg argument is passed to the fn function.
  • When the fn(arg) function application returns, the child process terminates.
  • The integer returned by fn is the exit code for the child process.
  • The child process may also terminate explicitly by calling exit(2) or after receiving a fatal signal.
Reference: