Operating Systems 📂 Introduction · 5 of 5 56 min read

Types of Schedulers & Process Control Block (PCB)

Understand how an operating system decides which process runs next and how it remembers every paused process. This deep-dive covers the three types of schedulers — Long-Term (Job), Short-Term (CPU), and Medium-Term (Swapper) — and the Process Control Block that makes context switching possible. Includes SVG diagrams, comparison tables, a C-code PCB implementation, a Round-Robin simulator, and a mapping to Linux's real task_struct.

Section 01

The Story That Explains Schedulers & PCB

The Hospital Emergency Room
Imagine a busy hospital. Hundreds of patients arrive daily, but only a handful of doctors, a few operation theatres, and limited beds exist. Someone must decide: who gets admitted, who sees a doctor next, and who is temporarily moved to a waiting ward to free up a bed for a critical case.

The hospital uses three levels of decision-makers: the reception (admits new patients), the triage nurse (decides the next patient the doctor sees), and the ward manager (temporarily moves stable patients out to make room).

Each patient also has a file at the foot of the bed — name, age, medicines given, current vitals, doctor assigned. Without that file, a shift-change would be chaos.

In an operating system, the three decision-makers are the three types of schedulers, and the file at the foot of the bed is the Process Control Block (PCB).

A modern computer runs hundreds of processes but has only a few CPU cores. The operating system must decide which process runs, when, and for how long. It also needs a place to remember everything about every process the moment it is paused. Galvin's textbook calls these two ideas the heart of process management.

💻
The Core Insight

Schedulers answer "which process runs next?". The Process Control Block answers "how do we remember exactly where a paused process was?". Together they make multitasking possible on a single CPU.


Section 02

Foundation — Process States (Quick Recap)

Before understanding schedulers, you need to know the five states a process moves through during its lifetime. Schedulers move processes between these states.

🔄 The Five Process States (Galvin)
New
The process is being created. It is in secondary memory, not yet admitted to main memory.
Ready
Loaded in main memory, waiting to be assigned a CPU. Multiple processes queue here.
Running
Instructions are being executed on the CPU. Only one process per core at a time.
Waiting
Blocked on I/O or an event. Cannot proceed until the event completes.
Terminated
Execution finished. The OS reclaims its memory and PCB.

Animated Process State Diagram

Watch a Process Travel Through Its States
Five-State Process Model — Live Watch process P1 flow through every state NEW READY RUNNING TERMINATED WAITING (I/O) admit dispatch interrupt exit I/O wait I/O done P1

The glowing token is process P1. Watch it get admitted (NEW → READY), dispatched (→ RUNNING), interrupted, blocked on I/O, resumed, then terminated. The current state pulses gold.


Section 03

Process Control Block (PCB) — What & Why

Every process in the system is represented by a Process Control Block, also called a Task Control Block. Galvin describes it as the data structure that fully identifies a process. When the OS pauses process A to run process B, it saves the entire "state" of A into A's PCB and loads B's state from B's PCB.

🔑
The One-Line Definition

A PCB is a per-process record kept by the kernel that stores everything needed to pause a process now and resume it later exactly where it left off — as if it never stopped.

Why the PCB Matters

💾
Context Preservation
Save & Restore
Stores CPU register values, program counter, and stack pointer when a process is preempted, so execution can resume bit-for-bit.
🔍
Process Identity
PID / PPID / UID
Uniquely identifies the process, its parent, and its owner. Enables signals, permissions, and tree relationships (like fork()).
📊
Resource Tracking
Memory / Files / I/O
Tracks memory limits, open file descriptors, and I/O devices held. On termination the OS uses this to reclaim everything cleanly.

Section 04

Fields Inside a PCB

Galvin lists the following fields as the minimum information every PCB must carry. Real OSes (Linux task_struct, Windows EPROCESS) extend this significantly.

Field Purpose Example Value
Process ID (PID)Unique integer identifier1247
Process StateNEW, READY, RUNNING, WAITING, TERMINATEDREADY
Program CounterNext instruction address0x7F3A2C10
CPU RegistersAll general-purpose & index registersRAX, RBX, RCX...
CPU Scheduling InfoPriority, pointers to scheduling queues, scheduling policypriority=15
Memory Management InfoBase & limit registers, page tables, segment tablesbase=0x1000000
Accounting InfoCPU time used, real time elapsed, time limits2.7 sec
I/O Status InfoList of open files, allocated I/O devicesfd=[0,1,2,7]
Parent PID (PPID)PID of process that created this one1023

Section 05

Animated Anatomy of a PCB

PCB Fields — Each Row Highlights In Sequence
Process Control Block (PCB) One block per process — kept in kernel memory Process ID (PID) 1247 Process State READY RUNNING Program Counter 0x7F3A2C10 CPU Registers RAX..R15 Priority 15 Memory Limits base+limit Open Files [0,1,2,7] CPU Time Used 2.7s Parent PID 1023 ← Identification ← CPU context ← Scheduling ← Resources ← Accounting

The gold scanner sweeps down the PCB, highlighting each field. CPU-time and process-state values tick live to show these fields update while the process runs.


Section 06

Types of Schedulers — The Three Levels

Operating systems use up to three schedulers, each operating at a different frequency and making a different decision. Galvin classifies them by how often they run and which state transition they control.

📚
Long-Term Scheduler
Job Scheduler
Decides which programs are admitted from the job pool into the ready queue. Runs rarely — seconds to minutes apart. Controls the degree of multiprogramming.
Short-Term Scheduler
CPU Scheduler
Picks which ready process gets the CPU next. Runs very frequently — every few milliseconds. Must be extremely fast to avoid wasting CPU on scheduling itself.
💾
Medium-Term Scheduler
Swapper
Temporarily removes processes from memory (swap-out) and reintroduces them later (swap-in). Used in time-sharing systems to reduce multiprogramming when memory is tight.
🔄
Frequency Rule

As you move from Long-Term → Short-Term, execution frequency increases and per-decision time budget decreases. Short-term schedulers must complete in microseconds; long-term schedulers can take milliseconds.

Animated — Relative Frequencies of the Three Schedulers

Watch Each Scheduler Fire At Its Own Rate
Long-Term (job scheduler) fires every few seconds Medium-Term (swapper) fires occasionally Short-Term (CPU scheduler) fires every ~10 ms Faster orbs = higher-frequency scheduler. The short-term fires ~1000× per long-term fire.

Every dot is one scheduler invocation. Short-term speeds by like a metronome; long-term crawls along; medium-term punches in occasionally.


Section 07

Long-Term Scheduler (Job Scheduler)

The Cinema Ticket Counter
Imagine a cinema hall with 300 seats. Outside, 800 people are queued up. The ticket counter lets exactly enough people in to fill the hall — no more, no less. If it admits too many, people stand in aisles (memory overflow). If too few, seats stay empty (idle CPU).

That ticket counter is the long-term scheduler.
🌟 Long-Term Scheduler Responsibilities
Job 1
Select which processes from the job pool (secondary storage) enter the ready queue.
Job 2
Balance CPU-bound and I/O-bound processes so the CPU and I/O devices stay busy together.
Job 3
Control the degree of multiprogramming — how many processes coexist in memory.
Job 4
Absent in most modern time-sharing systems (UNIX, Windows) — they simply admit every process immediately.
⚠️
A Bad Mix Kills Throughput

If the long-term scheduler admits only CPU-bound processes, the ready queue starves I/O devices. Admit only I/O-bound and the CPU sits idle. A good mix is the single biggest win of a long-term scheduler.


Section 08

Short-Term Scheduler (CPU Scheduler)

The short-term scheduler — also called the CPU scheduler or dispatcher — is invoked every time the CPU becomes free. That happens on every clock interrupt (typically 10 ms), every I/O wait, and every process exit.

Speed Is Everything

If short-term scheduling takes 10 ms per decision and the OS schedules every 100 ms, then 10% of CPU time is lost to scheduling itself. Real kernels finish this in microseconds.

Common CPU-Scheduling Algorithms

Algorithm Selects Preemptive? Typical Use
FCFS (First-Come-First-Served)Oldest process in queueNoBatch systems
SJF (Shortest Job First)Process with shortest burstOptionalBatch, theory
Priority SchedulingHighest-priority processOptionalReal-time systems
Round Robin (RR)Next in queue, time-slice enforcedYesTime-sharing (UNIX, Windows)
Multilevel QueueHighest non-empty queueYesSystems with many process classes

Animated Round-Robin — Time-Slice In Action

Round-Robin Scheduling With 3 Processes
Round Robin (Time Quantum = 10 ms) CPU P1 P2 P3 P1 P2 P3 Ready Queue t=0 t=30 ms P1 P2 P3 Each colored slot = 10 ms quantum

The gold token orbits the queue → CPU → queue, giving each process its 10 ms slice. The right-hand timeline shows the same story as a Gantt chart.


Section 09

Medium-Term Scheduler (Swapper)

The Hospital's Overflow Ward
When the emergency room fills up but a critical patient arrives, the ward manager moves a stable patient out to the overflow ward. Later, when a bed frees up, the stable patient returns.

That's swapping. The stable patient never lost their file (PCB); they just moved location temporarily.

The medium-term scheduler performs swapping: temporarily moving a partially-executed process from main memory to secondary storage, then bringing it back later. This reduces the degree of multiprogramming when memory pressure spikes.

💾 Why Swap?
Reason 1
Free up memory for higher-priority processes that need to be admitted.
Reason 2
Improve the CPU-bound / I/O-bound mix after the long-term scheduler made a suboptimal admission.
Reason 3
Reduce thrashing when too many processes are competing for the page frame.

Animated Swap-Out & Swap-In

Watch A Process Get Swapped To Disk And Back
MAIN MEMORY (RAM) P1 (running) P2 (ready) P3 (ready) [ empty ] free frame SWAP SPACE (DISK) [ empty slot ] P3 (swapped out) P3 swap-out → ← swap-in

P3's box drifts from RAM to disk (swap-out), sits there while another process runs, then drifts back (swap-in) — its PCB stayed in the kernel the entire time.

🔊
Swapping Is Expensive

Moving a process image to disk and back costs milliseconds — much slower than a context switch. Modern OSes prefer paging (moving individual pages) instead of full-process swapping, but the medium-term scheduler concept still applies.


Section 10

Animated — All Three Schedulers Working Together

Complete Scheduler Pipeline (Live)
Job Pool (secondary storage) Long-Term Scheduler admits jobs READY QUEUE in main memory [ P1 | P2 | P3 | ... ] Short-Term Scheduler picks next-to-run every ~10 ms CPU RUNNING Waiting Queue (I/O) SUSPENDED (on disk) swapped-out processes Medium-Term Scheduler (Swap) P1 P2 P3 Live tokens flow through queues. Watch P1 complete, P2 loop through I/O, and P3 get swapped out and back.

Every dot is a process. The green scheduler admits; the amber scheduler dispatches; the purple scheduler swaps. The pipeline never stops.


Section 11

Comparison — All Three Schedulers

Property Long-Term Short-Term Medium-Term
Also calledJob SchedulerCPU Scheduler / DispatcherSwapper
Speed of executionSlowestFastestMedium
Frequency of invocationSeconds–minutesMillisecondsOccasional
State transition controlledNEW → READYREADY → RUNNINGREADY ↔ SUSPENDED
Controls degree of multiprogrammingYesNoYes
Present in time-sharing OS?RarelyAlwaysSometimes
Decision goalGood process mixMax CPU utilisation, low latencyRelieve memory pressure

Section 12

Animated — Context Switching With PCB

The Save & Restore Dance
PCB(P1) state, PC, registers state: RUNNING READY PC: 0x4021A0 RAX: 0x00A9F3 SP: 0x7FFF01 CPU REGISTERS holds active process Executing P1 « switching » Executing P2 PC: 0x4021A0 0x40332C RAX: 0x00A9F3 0x0F1A22 PCB(P2) state, PC, registers state: READY RUNNING PC: 0x40332C RAX: 0x0F1A22 SP: 0x7FFEB0 SAVE LOAD 1. P1 is running normally 2. Interrupt! Save CPU state into PCB(P1) 3. Load PCB(P2) into CPU 4. P2 continues from where it paused Context switch = save one PCB, load another. That's it.

Read the status line at the bottom to follow the four-step dance: run → save PCB(P1) → load PCB(P2) → continue P2.

⚠️
Context Switching Is Pure Overhead

No user work is done during a context switch. On modern hardware it costs 1–10 microseconds. Choosing a shorter time-quantum in Round Robin gives snappier response but more overhead — a classic throughput vs latency tradeoff.


Section 13

Practical Example — Modelling a PCB in C

Here is a simplified PCB structure showing what a real kernel writes. This is close to the classical Galvin form.

/* pcb.h - Simplified Process Control Block */
#include <stdint.h>

typedef enum {
    STATE_NEW,
    STATE_READY,
    STATE_RUNNING,
    STATE_WAITING,
    STATE_TERMINATED
} ProcessState;

typedef struct {
    /* --- Identification --- */
    uint32_t pid;                   // unique process ID
    uint32_t ppid;                  // parent PID
    uint32_t uid;                   // owner user ID

    /* --- Process State --- */
    ProcessState state;

    /* --- CPU Context (saved on preemption) --- */
    uint64_t program_counter;
    uint64_t stack_pointer;
    uint64_t registers[16];        // RAX..R15 on x86-64
    uint64_t flags;

    /* --- Scheduling Info --- */
    int      priority;              // 0 = highest
    uint64_t time_slice_remaining;  // for Round Robin
    struct PCB *next_in_queue;    // linked-list pointer

    /* --- Memory Management --- */
    uint64_t base_register;
    uint64_t limit_register;
    void    *page_table;

    /* --- Accounting --- */
    uint64_t cpu_time_used_us;      // microseconds
    uint64_t creation_time;

    /* --- I/O Status --- */
    int      open_files[32];        // file descriptor table
    int      num_open;
} PCB;

Simulating a Round-Robin Short-Term Scheduler

/* Very simplified RR scheduler over a ready-queue of PCBs */
#define QUANTUM_US 10000   // 10 ms time quantum

PCB *ready_head = NULL;    // front of ready queue
PCB *running    = NULL;    // currently on CPU

void enqueue_ready(PCB *p) {
    p->state = STATE_READY;
    p->next_in_queue = NULL;
    if (!ready_head) { ready_head = p; return; }
    PCB *t = ready_head;
    while (t->next_in_queue) t = t->next_in_queue;
    t->next_in_queue = p;
}

void context_switch(PCB *from, PCB *to) {
    // 1. Save current CPU state into 'from' PCB
    if (from) {
        from->program_counter = cpu_get_pc();
        cpu_save_registers(from->registers);
        from->state = STATE_READY;
        enqueue_ready(from);
    }
    // 2. Load 'to' PCB into CPU
    cpu_load_registers(to->registers);
    cpu_set_pc(to->program_counter);
    to->state = STATE_RUNNING;
    to->time_slice_remaining = QUANTUM_US;
    running = to;
}

/* Called on every timer interrupt (every 1 ms, say) */
void timer_tick(uint64_t elapsed_us) {
    if (!running) return;
    running->cpu_time_used_us  += elapsed_us;
    running->time_slice_remaining -= elapsed_us;

    if (running->time_slice_remaining <= 0) {
        // Time-slice expired -> preempt
        PCB *next = ready_head;
        if (next) {
            ready_head = next->next_in_queue;
            context_switch(running, next);
        }
    }
}
SIMULATED TRACE
t=0 ms → P1 dispatched (state=RUNNING, quantum=10 ms) t=10 ms → quantum expired save PC=0x4021A0, regs, state=READY into PCB(P1) load PCB(P2): PC=0x40332C, regs, state=RUNNING t=15 ms → P2 issues read() → state=WAITING dispatch P3 from ready queue t=25 ms → I/O complete, P2 back to READY (via medium-term / short-term path) t=30 ms → P3 quantum expired, save, load P1 P1 resumes at PC=0x4021A0 exactly where it left
🏆
Key Takeaway

The PCB is what makes context_switch() possible. Without saving/restoring PC and registers, resuming a paused process would be like re-reading a book from page 1 every time you put it down.


Section 14

Real-World — Linux's task_struct

Linux's PCB is called task_struct and lives in <linux/sched.h>. It has over 100 fields, but the classical Galvin subset is clearly visible.

/* Excerpt from Linux kernel (simplified) */
struct task_struct {
    /* Identification */
    pid_t              pid;
    pid_t              tgid;                // thread group id
    struct task_struct *parent;
    kuid_t             uid;

    /* State & scheduling */
    long               state;               // TASK_RUNNING, TASK_INTERRUPTIBLE...
    int                prio;                // current priority
    int                static_prio;         // nice value based
    struct sched_entity se;                  // CFS scheduling entity
    unsigned int       policy;              // SCHED_NORMAL, SCHED_FIFO...

    /* CPU context — saved in thread_struct */
    struct thread_struct thread;

    /* Memory management */
    struct mm_struct   *mm;

    /* Open files */
    struct files_struct *files;

    /* Accounting */
    u64                utime, stime;       // user/system CPU time
    u64                start_time;
};
📜
Textbook → Practice

Every Galvin field maps to a Linux field: PID → pid, State → state, CPU context → thread_struct, Memory info → mm_struct, Open files → files_struct, Priority → prio. The textbook is not academic fluff — it is exactly what real kernels implement.


Section 15

Golden Rules

📚 Schedulers & PCB — Non-Negotiable Rules
1
There is exactly one PCB per process. The kernel creates it on process creation and destroys it on termination — never before, never after.
2
The short-term scheduler must be fast. Every microsecond it spends deciding is a microsecond stolen from user processes. Keep the algorithm O(1) or O(log n) — never O(n²).
3
The long-term scheduler controls degree of multiprogramming. Too high = memory thrashing, too low = idle CPU. A good mix of CPU-bound and I/O-bound jobs beats raw quantity every time.
4
Context switching is pure overhead. It does zero user work. Measure it, minimise it, and understand it as the cost you pay for multitasking.
5
Modern time-sharing OSes (Linux, Windows, macOS) skip the long-term scheduler — they admit every process immediately and rely on paging & the short-term scheduler. But the concept still governs real-time and batch systems.
6
When a process is swapped out by the medium-term scheduler, its PCB stays in kernel memory. Only its user-space image goes to disk. The PCB is small and precious.
7
Never confuse "scheduler" with "dispatcher". The scheduler decides who runs next; the dispatcher performs the context switch and hands the CPU over. Both live inside the short-term path.
You have completed Introduction. View all sections →