Fundamentals 28 min read

Master Linux Process Management: Fork, vfork, exec, wait, zombie & orphan processes

This tutorial explains core Linux process concepts—including the difference between programs and processes, how to view and identify processes, detailed usage of fork and vfork for creating child processes, process termination, zombie and orphan handling, and practical examples of exec, system, and popen functions with C code.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Master Linux Process Management: Fork, vfork, exec, wait, zombie & orphan processes

What is a program and what is a process?

A program is a static file on disk (e.g., compiled with gcc xxx.c -o prog), while a process is a running instance of that program, created when the OS loads the executable into memory.

How to list processes

Use ps -aux (often combined with grep) or top to view active processes.

Process identifiers (PID)

Every process has a unique non‑negative PID. PID 0 is the swapper (idle) process, PID 1 is the init process.

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
pid_t getppid(void);

Example to print the current PID:

#include <stdio.h>
#include <unistd.h>
int main(){
    pid_t pid = getpid();
    printf("my pid is %d
", pid);
    return 0;
}

Creating processes with fork()

fork()

creates a child process. It returns 0 in the child, the child's PID in the parent, and –1 on error.

#include <stdio.h>
#include <unistd.h>
int main(){
    pid_t pid = fork();
    if (pid == 0) {
        printf("child pid %d
", getpid());
    } else if (pid > 0) {
        printf("parent pid %d, child pid %d
", getpid(), pid);
    } else {
        perror("fork");
    }
    return 0;
}

Using fork() return values to distinguish parent/child

Example that prints different messages based on the return value:

#include <stdio.h>
#include <unistd.h>
int main(){
    pid_t pid = fork();
    if (pid > 0) {
        printf("this is father, pid=%d
", getpid());
    } else if (pid == 0) {
        printf("this is child, pid=%d
", getpid());
    }
    return 0;
}

Process creation scenarios

Typical uses of fork() include a server spawning a child to handle a client request while the parent continues listening, or a shell creating a child that immediately calls exec() to run another program.

fork memory layout
fork memory layout

Process termination

Processes can exit normally via return from main, exit(), _exit(), or _Exit(). Abnormal termination occurs via signals (e.g., abort(), Ctrl+C).

Waiting for child processes

Parent processes use wait() or waitpid() to collect a child's exit status, preventing zombie processes.

#include <sys/wait.h>
pid_t pid = fork();
if (pid == 0) {
    // child work
    exit(5);
} else {
    int status;
    waitpid(pid, &status, 0);
    printf("child exited with status %d
", WEXITSTATUS(status));
}

Zombie and orphan processes

If a parent does not wait for its child, the child becomes a zombie after exiting. If the parent exits before the child, the child becomes an orphan and is adopted by the init process (PID 1), which later reaps it.

Replacing a process image with exec() family

After fork(), a child can call exec() to replace its memory image with a new program. The process ID remains unchanged.

#include <unistd.h>
int main(){
    execl("/bin/ls", "ls", "-l", (char *)NULL);
    perror("execl"); // only reached on failure
    return 1;
}

The suffix letters indicate usage:

l : argument list is passed as separate parameters.

p : search PATH for the executable.

v : arguments are supplied as an array.

e : a custom environment array is provided.

Running commands with system()

system()

forks a child that runs /bin/sh -c "command". It returns the command's exit status, 127 if the shell cannot be executed, or –1 on failure.

Capturing command output with popen()

popen()

creates a pipe to a child process. Use mode "r" to read the command's stdout, or "w" to write to its stdin.

#include <stdio.h>
int main(){
    char buf[1024];
    FILE *fp = popen("ps", "r");
    size_t n = fread(buf, 1, sizeof(buf)-1, fp);
    buf[n] = '\0';
    printf("ps output:
%s", buf);
    pclose(fp);
    return 0;
}
popen example
popen example

These tools together provide a complete workflow for creating, managing, and cleaning up processes in Linux.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

LinuxprocessC programmingforkexec
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.