Process as Virtualisation
A process is the operating system's fundamental unit of computation. It represents a running program in execution, complete with its own memory space, registers, file descriptors, and execution context. In essence, the process is the OS's first and most important form of virtualisation: it makes a single physical CPU appear as many virtual CPUs.
The Virtual CPU
When you run a program, the OS creates a process. The process believes it has exclusive access to the CPU, but the OS rapidly switches between processes, giving each a small time slice. This technique is called time-sharing or time-slicing.
Each process has its own:
- Program Counter (PC): The address of the next instruction to execute.
- Stack Pointer (SP): The current position on the call stack.
- General-purpose registers: Temporary storage for arithmetic and addressing.
- Memory Management Unit (MMU) state: Page tables defining the process's virtual address space.
When the OS switches from one process to another (a context switch), it saves the current process's register state to memory and loads the next process's state. The CPU then resumes execution as if nothing happened.
Memory Virtualisation
Each process runs in its own virtual address space, isolated from all other processes. On a 64-bit system, each process might believe it has 128 TB of memory starting at address 0, while the physical RAM might be only 16 GB.
The Memory Management Unit (MMU) translates virtual addresses to physical addresses using page tables. The OS controls these page tables, enabling:
- Protection: A process cannot read or write another process's memory.
- Swapping: Inactive pages can be written to disk, freeing RAM for active processes.
- Copy-on-Write (COW): Parent and child processes after fork share physical pages until one writes, at which point the OS copies the page.
- Memory Mapping: Files can be mapped directly into a process's address space using mmap.
Process Creation and Lifecycle
Processes are created using system calls:
- fork: Creates a child process that is a copy of the parent.
- exec: Replaces the current process image with a new program.
- clone: Linux-specific system call for creating processes with fine-grained sharing (used by threads and containers).
Processes exit using exit, returning a status code to their parent. The parent retrieves this status using wait or waitpid.
Process States
A process can be in one of several states:
- Running: Executing on a CPU.
- Ready: Waiting for a CPU to become available.
- Sleeping (Interruptible): Waiting for an event (I/O completion, signal).
- Sleeping (Uninterruptible): Waiting for I/O (usually short-lived).
- Zombie: The process has exited but its parent has not yet collected its exit status.
- Stopped: Suspended by a signal (SIGSTOP, SIGTSTP).
Process Identifiers
Each process has a unique Process ID (PID). PID 1 is always the init system (systemd, SysVinit, etc.). PIDs are assigned sequentially from a pool, with the maximum PID configurable via /proc/sys/kernel/pid_max.
Processes also have:
- Parent PID (PPID): The PID of the creating process.
- Real/Effective/Saved UID/GID: For permission checking and setuid binaries.
- Thread Group ID (TGID): For multi-threaded processes.
Virtualisation Analogy
Think of a process as a virtual machine that runs one program:
- The CPU virtualisation gives each process its own registers and program counter.
- The memory virtualisation gives each process its own isolated address space.
- The I/O virtualisation gives each process its own file descriptor table.
The OS is the hypervisor, managing these virtual machines (processes) and switching between them faster than any physical machine could.
Related Articles
- Init system: Article - Init system
- Process security: Article - OS security functions (uid/gid, ulimit, apparmor, selinux)
- Process isolation: Article - Lightweight OS virtualisation techniques (chroot, namespace)