🧠 POSIX/Unix Process Creation Cheatsheet

🎯 Visual Process Creation Flowchart

PARENT PROCESS
    |
    |-- fork() / vfork() / clone()
    |        |
    |        +-- CHILD
    |              |
    |              +-- exec*() to load new program
    |
    |-- posix_spawn() / posix_spawnp()
    |        |
    |        +-- CHILD already loaded with new program
    |
    +-- Parent monitors child (wait(), waitpid(), waitid())

βœ… Key point:

πŸ—ΊοΈ Logical Flow Summary

Step Action Functions
1 Create child fork(), vfork(), clone(), posix_spawn(), posix_spawnp()
2 Load executable (child only) exec*()
3 Monitor child (parent) wait(), waitpid(), waitid()

1. πŸ‘Ά Child Creation (Parent Spawns a Child Process)

Function Purpose Notes
fork() Duplicate parent process Standard and safe
vfork() Create child for immediate exec Dangerous (shared memory) but faster
clone() (Linux-specific) Fine-grained process/thread creation Manual stack needed
posix_spawn() Create + load new program atomically High-level alternative
posix_spawnp() Same as posix_spawn() but searches $PATH High-level alternative

⚑ Quick Comparison: fork() vs vfork() vs clone() vs posix_spawn() vs posix_spawnp()

Feature fork() vfork() clone() posix_spawn() posix_spawnp()
Memory duplicated? Yes (Copy-on-Write) No (shared memory) Configurable No No
Needs manual exec()? Yes Yes (immediately!) Yes No No
Stack required? No No Yes (manual allocation) No No
$PATH search? N/A (needs manual exec) N/A (needs manual exec) N/A (needs manual exec) No Yes
Portability Very portable Legacy, discouraged Linux-specific POSIX standard POSIX standard
Risk Level Safe Dangerous Advanced usage Safe Safe
Use Case General process creation Fast exec after fork Fine-grained control Simple, safe spawning Same, but command lookup

πŸ› οΈ When to Prefer fork() vs posix_spawn()

Situation Use Why
Traditional Unix/Linux server fork() + exec() Full control, classic behavior
Minimal code changes needed fork() Simple copy-paste codebases
Security/Sandboxed environments (e.g.Β iOS, macOS, Android) posix_spawn() fork() may be restricted or banned
Performance critical (no Copy-on-Write cost) posix_spawn() Faster than fork()+exec() together
Very limited memory available posix_spawn() No double memory footprint

Examples:

1.1 fork()

pid_t pid = fork();

1.2 vfork()

pid_t pid = vfork();

1.3 clone() (Simple Example)

#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int child_fn(void *arg) {
    printf("Child says hi!\n");
    _exit(0);
}

#define STACK_SIZE 1024*1024

int main() {
    char *stack = malloc(STACK_SIZE);
    if (!stack) { perror("malloc"); exit(1); }

    pid_t pid = clone(child_fn, stack + STACK_SIZE, SIGCHLD, NULL);
    if (pid == -1) { perror("clone"); exit(1); }

    waitpid(pid, NULL, 0);
    free(stack);
}

1.4 posix_spawn() (Simple Example)

#include <spawn.h>
#include <unistd.h>

extern char **environ;

int main() {
    pid_t pid;
    char *argv[] = {"ls", "-l", NULL};
    posix_spawn(&pid, "/bin/ls", NULL, NULL, argv, environ);
    waitpid(pid, NULL, 0);
}

1.5 posix_spawnp() (Simple Example)

#include <spawn.h>
#include <unistd.h>

extern char **environ;

int main() {
    pid_t pid;
    char *argv[] = {"ls", "-l", NULL};
    posix_spawnp(&pid, "ls", NULL, NULL, argv, environ);
    waitpid(pid, NULL, 0);
}

2. πŸ“¦ Loading a New Program (Child Replaces Itself)

Function Purpose Notes
execl() Load program with explicit args
execv() Load program with array of args
execle() Explicit args + new environment Completely replaces environment
execve() Array of args + new environment Completely replaces environment
execlp() Explicit args, uses $PATH
execvp() Array of args, uses $PATH
execvpe() Array of args + new environment + $PATH GNU extension

Examples:

2.1 execl()

execl("/bin/ls", "ls", "-l", (char *)NULL);

2.2 execv()

char *args[] = {"ls", "-l", NULL};
execv("/bin/ls", args);

2.3 execle()

char *envp[] = {"MYVAR=value", NULL};
execle("/bin/ls", "ls", "-l", (char *)NULL, envp);

Environment behavior:
πŸ”΅ Fully replaces existing environment.
πŸ”΅ Only what you specify is visible inside the new process.

2.4 execve()

char *args[] = {"ls", "-l", NULL};
char *envp[] = {"MYVAR=value", NULL};
execve("/bin/ls", args, envp);

Environment behavior:
πŸ”΅ Fully replaces existing environment.

2.5 execlp()

execlp("ls", "ls", "-l", (char *)NULL);

2.6 execvp()

char *args[] = {"ls", "-l", NULL};
execvp("ls", args);

2.7 execvpe() (GNU only)

char *args[] = {"ls", "-l", NULL};
char *envp[] = {"MYVAR=value", NULL};
execvpe("ls", args, envp);

Environment behavior:
πŸ”΅ Fully replaces environment, and searches executable in $PATH.

3. πŸ•΅οΈ Monitoring and Reaping Children

Function Purpose Notes
wait() Wait for any child
waitpid() Wait for specific child Can be non-blocking
waitid() Get detailed info about child exit

Examples:

3.1 wait()

int status;
pid_t pid = wait(&status);

3.2 waitpid()

int status;
pid_t pid = waitpid(child_pid, &status, 0);

3.3 waitid()

siginfo_t info;
waitid(P_PID, child_pid, &info, WEXITED);

πŸ“‹ Notes:

Logo
buildsoftwaresystems.com