Topic Overview

PCB (Process Control Block)

Learn Process Control Block structure that stores process state and context information for process management and context switching.

Medium9 min read

PCB (Process Control Block)

Why This Matters

Think of a PCB like a personnel file for an employee. It contains everything the company needs to know: ID, job description, current task, performance history, etc. When the employee switches tasks, the file is updated. A PCB does the same for processes—it stores all information the OS needs: process ID, CPU state, memory info, scheduling info. When the OS switches between processes, it uses the PCB.

This matters because the OS manages many processes simultaneously. Each process needs its own PCB to track its state. When the OS switches from one process to another (context switch), it saves the current process's state to its PCB and loads the next process's state from its PCB. Understanding PCBs helps you understand how the OS manages processes and performs context switches.

In interviews, when someone asks "How does the OS manage processes?", they're testing whether you understand PCBs. Do you know what information is stored in a PCB? Do you understand how context switching works? Most engineers don't. They just run programs and assume the OS handles it.

What Engineers Usually Get Wrong

Most engineers think "PCB is just process information." But PCB is critical for context switching. When the OS switches processes, it saves CPU registers, program counter, stack pointer, etc. to the PCB, then loads the next process's values. Without PCBs, the OS couldn't switch between processes. Understanding this helps you understand how multitasking works.

Engineers also don't understand that PCBs consume memory. Each process has a PCB (typically a few KB). With thousands of processes, PCBs consume significant memory. Understanding this helps you understand process limits and memory usage.

How This Breaks Systems in the Real World

A service was creating many processes (one per request). Each process had a PCB. With thousands of requests, thousands of PCBs were created, consuming memory. The system ran out of memory. The fix? Use threads instead of processes (threads share a PCB), or use a process pool to reuse processes. Understanding PCBs helps you understand why threads are lighter than processes.

Another story: A service was experiencing slow context switches. The OS was switching between processes frequently, and each switch required saving/loading PCB data. This overhead slowed the system. The fix? Reduce context switches. Use fewer processes, or optimize scheduling. Understanding PCBs helps you understand context switch overhead.


What is a PCB?

PCB (Process Control Block) contains:

  • Process identification: Process ID (PID), parent PID
  • CPU state: Registers, program counter, stack pointer
  • Memory information: Page table, memory limits
  • I/O status: Open files, devices
  • Scheduling information: Priority, state, CPU time
  • Accounting: Start time, CPU time used

Purpose:

  • Context switching: Save/restore process state
  • Process management: Track process information
  • Scheduling: Determine which process to run
  • Resource management: Track resources used

PCB Structure

Typical PCB Fields

PCB Structure:
  - Process ID (PID)
  - Parent Process ID (PPID)
  - Process State (Ready, Running, Blocked, etc.)
  - Program Counter (PC)
  - CPU Registers (AX, BX, CX, DX, SP, etc.)
  - Memory Management Info
    - Page table pointer
    - Memory limits
    - Base and limit registers
  - I/O Status
    - Open files
    - I/O devices
  - Scheduling Information
    - Priority
    - CPU time used
    - Time quantum remaining
  - Accounting Information
    - Start time
    - CPU time
    - Memory used

PCB and Process States

Process states stored in PCB:

  • NEW: Process being created
  • READY: Process ready to run, waiting for CPU
  • RUNNING: Process currently executing
  • BLOCKED: Process waiting for I/O or event
  • TERMINATED: Process finished

State transitions:

NEW → READY → RUNNING → READY (time slice expired)
RUNNING → BLOCKED (I/O wait)
BLOCKED → READY (I/O complete)
RUNNING → TERMINATED (process ends)

PCB and Context Switching

Context switching uses PCB:

1. Save current process state to PCB
   - Save CPU registers
   - Save program counter
   - Save memory management info

2. Load next process state from PCB
   - Load CPU registers
   - Load program counter
   - Load memory management info

Examples

PCB Implementation

// PCB structure in C
typedef struct {
    // Process identification
    int pid;
    int ppid;  // Parent process ID
    
    // Process state
    enum {
        NEW,
        READY,
        RUNNING,
        BLOCKED,
        TERMINATED
    } state;
    
    // CPU state
    int program_counter;
    int stack_pointer;
    int registers[16];  // CPU registers
    
    // Memory management
    void* page_table;
    int memory_base;
    int memory_limit;
    
    // I/O status
    FILE* open_files[10];
    int io_devices[5];
    
    // Scheduling
    int priority;
    int cpu_time_used;
    int time_quantum;
    
    // Accounting
    time_t start_time;
    int cpu_time;
    int memory_used;
} PCB;

PCB Operations

class ProcessControlBlock:
    def __init__(self, pid):
        # Process identification
        self.pid = pid
        self.ppid = None
        
        # Process state
        self.state = 'NEW'
        
        # CPU state
        self.program_counter = 0
        self.stack_pointer = 0
        self.registers = {
            'AX': 0, 'BX': 0, 'CX': 0, 'DX': 0,
            'SP': 0, 'BP': 0, 'SI': 0, 'DI': 0
        }
        
        # Memory management
        self.page_table = None
        self.memory_base = 0
        self.memory_limit = 0
        
        # I/O status
        self.open_files = []
        self.io_devices = []
        
        # Scheduling
        self.priority = 0
        self.cpu_time_used = 0
        self.time_quantum = 10  # milliseconds
        
        # Accounting
        self.start_time = time.time()
        self.cpu_time = 0
        self.memory_used = 0
    
    def save_cpu_state(self, cpu_state):
        """Save CPU state to PCB"""
        self.program_counter = cpu_state['PC']
        self.stack_pointer = cpu_state['SP']
        self.registers = cpu_state['registers'].copy()
    
    def restore_cpu_state(self):
        """Restore CPU state from PCB"""
        return {
            'PC': self.program_counter,
            'SP': self.stack_pointer,
            'registers': self.registers.copy()
        }
    
    def update_state(self, new_state):
        """Update process state"""
        self.state = new_state
    
    def get_info(self):
        """Get process information"""
        return {
            'pid': self.pid,
            'state': self.state,
            'cpu_time': self.cpu_time,
            'memory_used': self.memory_used
        }

Common Pitfalls

  • Not saving all state: Missing registers causes corruption. Fix: Save all CPU state
  • PCB corruption: PCB overwritten. Fix: Protect PCB, use proper locking
  • Memory leaks: PCBs not freed. Fix: Free PCB when process terminates
  • State inconsistency: PCB state doesn't match process. Fix: Update PCB on state changes

Interview Questions

Beginner

Q: What is a PCB and what information does it store?

A:

PCB (Process Control Block) is a data structure storing all information about a process.

Information stored:

  • Process identification: PID, parent PID
  • CPU state: Registers, program counter, stack pointer
  • Memory information: Page table, memory limits
  • I/O status: Open files, devices
  • Scheduling: Priority, state, CPU time
  • Accounting: Start time, CPU time used

Purpose:

  • Context switching: Save/restore process state
  • Process management: Track process information
  • Scheduling: Determine which process to run

Example:

PCB for Process 123:
  PID: 123
  State: RUNNING
  PC: 0x1234
  Registers: [AX=10, BX=20, ...]
  Memory: Page table at 0x5000
  Priority: 5

Intermediate

Q: Explain how PCB is used in context switching and process scheduling.

A:

Context Switching:

  1. Save current process state

    # Save CPU state to PCB
    current_process.pcb.save_cpu_state(cpu_state)
    current_process.pcb.state = 'READY'
    
  2. Select next process

    next_process = scheduler.select_next()
    
  3. Restore next process state

    # Load CPU state from PCB
    cpu_state = next_process.pcb.restore_cpu_state()
    next_process.pcb.state = 'RUNNING'
    

Process Scheduling:

Scheduler uses PCB information:

  • State: Only schedule READY processes
  • Priority: Higher priority processes first
  • CPU time: Track time used for scheduling decisions
  • I/O status: Blocked processes not scheduled

Example:

def schedule():
    ready_processes = [p for p in processes if p.pcb.state == 'READY']
    
    # Sort by priority
    ready_processes.sort(key=lambda p: p.pcb.priority, reverse=True)
    
    # Select highest priority
    next_process = ready_processes[0]
    
    # Context switch
    switch_context(current_process, next_process)

PCB fields used:

  • State: Determine if process can run
  • Priority: Scheduling decision
  • CPU time: Time slice management
  • Registers: Context switching

Senior

Q: Design a PCB management system for an OS that handles millions of processes. How do you optimize PCB storage, context switching, and process lookup?

A:

class PCBManagementSystem {
  private pcbs: Map<number, PCB>;
  private pcbPool: PCBPool;
  private index: ProcessIndex;
  
  constructor() {
    this.pcbs = new Map();
    this.pcbPool = new PCBPool();
    this.index = new ProcessIndex();
  }
  
  // 1. PCB Allocation
  class PCBPool {
    private pool: PCB[];
    
    allocate(pid: number): PCB {
      // Reuse from pool or create new
      let pcb = this.pool.pop();
      if (!pcb) {
        pcb = new PCB(pid);
      } else {
        pcb.reset(pid);
      }
      return pcb;
    }
    
    deallocate(pcb: PCB): void {
      // Return to pool
      pcb.cleanup();
      this.pool.push(pcb);
    }
  }
  
  // 2. Optimized PCB Structure
  class PCB {
    // Compact structure for memory efficiency
    private compact: CompactPCB;
    private extended: ExtendedPCB; // Only when needed
    
    saveCPUState(cpuState: CPUState): void {
      // Save only modified registers (lazy saving)
      this.compact.modifiedRegisters = this.getModified(cpuState);
      this.compact.programCounter = cpuState.PC;
    }
  }
  
  // 3. Fast Process Lookup
  class ProcessIndex {
    private byPid: Map<number, PCB>;
    private byState: Map<string, Set<number>>;
    private byPriority: PriorityQueue;
    
    getByPid(pid: number): PCB {
      return this.byPid.get(pid);
    }
    
    getReadyProcesses(): PCB[] {
      const pids = this.byState.get('READY');
      return Array.from(pids).map(pid => this.byPid.get(pid));
    }
    
    getHighestPriority(): PCB {
      return this.byPriority.peek();
    }
  }
  
  // 4. Context Switching Optimization
  optimizeContextSwitch(): void {
    // Lazy register saving: Only save modified registers
    // Use CPU hardware support for fast context switch
    // Cache frequently accessed PCBs
  }
  
  // 5. Memory Optimization
  optimizeMemory(): void {
    // Compact PCB structure
    // Extended info only when needed
    // Pool PCBs for reuse
  }
}

Features:

  1. PCB pool: Reuse PCBs to reduce allocation overhead
  2. Compact structure: Minimize memory usage
  3. Fast lookup: Index by PID, state, priority
  4. Lazy saving: Only save modified registers
  5. Memory efficient: Compact structure, extended when needed

  • PCB: Data structure storing all process information

  • Contents: PID, CPU state, memory info, I/O status, scheduling info

  • Context switching: Save/restore process state using PCB

  • Process scheduling: Scheduler uses PCB information (state, priority)

  • Process states: NEW, READY, RUNNING, BLOCKED, TERMINATED

  • Memory management: PCB stores page table, memory limits

  • Best practices: Save all state, protect PCB, free when process terminates

  • Context Switching - How PCB is used to save and restore process state during context switches

  • Process vs Thread - Understanding processes that have PCBs and how threads relate to PCBs

  • Scheduling Algorithms - How the scheduler uses PCB information (state, priority) for scheduling decisions

  • Memory Management - How PCB stores memory information (page table, memory limits)

  • System Calls - How system calls update PCB information (I/O status, resource usage)

Key Takeaways

PCB: Data structure storing all process information

Contents: PID, CPU state, memory info, I/O status, scheduling info

Context switching: Save/restore process state using PCB

Process scheduling: Scheduler uses PCB information (state, priority)

Process states: NEW, READY, RUNNING, BLOCKED, TERMINATED

Memory management: PCB stores page table, memory limits

Best practices: Save all state, protect PCB, free when process terminates


About the author

InterviewCrafted helps you master system design with patience. We believe in curiosity-led engineering, reflective writing, and designing systems that make future changes feel calm.