The idea: the order of the queue decides the seek

A hard disk reads and writes with a head on an arm that moves across the platter. The rings it can stop over are cylinders, here numbered 0 to 199. Moving the arm (a seek) takes milliseconds, so when several requests are waiting, the order in which they are served decides how far the head travels. A disk scheduling algorithm picks that order.

Two seek-path charts for the queue 98, 183, 37, 122, 14, 124, 65, 67 with the head at 53. FCFS zig-zags across the disk in arrival order, 640 cylinders in all. SSTF goes 65, 67, 37, 14, 98, 122, 124, 183, 236 cylinders in all
The same eight requests: in arrival order the head travels 640 cylinders, closest-first only 236.

The canvas uses the classic textbook queue: requests for cylinders 98, 183, 37, 122, 14, 124, 65, 67, the head at cylinder 53. The chart under the cylinder axis is the head's path: one row per stop, top to bottom. Time is counted in ticks: one tick is the head moving one cylinder, so the total seek distance is also the time the run takes. Pick an algorithm and press Run, or run a demo.

FCFS: first come, first served

FCFS serves the requests in the order they arrived. It is fair: nobody is overtaken. But it ignores where the head is, so it swings from 122 to 14 and back to 124. Demo 1 travels 640 cylinders.

SSTF and starvation

SSTF (shortest seek time first) always goes to the closest waiting request. From 53 that is 65 (12 away), then 67, then 37, 14, and only then the high cylinders. Demo 2 travels 236 cylinders, the lowest total on this queue.

The catch is starvation. SSTF never looks at how long a request has waited. If new requests keep arriving near the head, a far request is passed over again and again. In Demo 8 a request for cylinder 120 waits from t = 0 while twelve near requests (45–66) arrive one after another. SSTF serves 120 last, 13th of 13, after 205 ticks; if the stream did not end, it would wait for ever. LOOK on the same queue serves 120 second, after 67 ticks, and nobody waits longer than 133.

SCAN and C-SCAN: the elevator

SCAN moves the head one way and serves every request it passes, like an elevator. When nothing is left ahead, it still runs on to the edge of the disk and then turns back. A request is never passed over for long: at worst it waits for one sweep out and one sweep back. With the head moving up, Demo 3 serves 65, 67, 98, 122, 124, 183, runs on to 199, then comes down for 37 and 14: 331 cylinders.

SCAN is unfair in a quieter way. Just after the head turns, the cylinders it has just passed get a second visit soon, while the far end waits for the whole round trip. C-SCAN (circular SCAN) serves only on the way up. At 199 the head returns straight to cylinder 0 without serving anything and sweeps up again, so every cylinder waits about the same time. Demo 4: 53 → 183 → 199, back to 0, then 14 and 37: 382 cylinders, the return of 199 counted.

Four seek-path charts with the head at 53 moving up. SCAN serves up to 183, runs on to 199, then comes down to 37 and 14, 331 cylinders. C-SCAN runs to 199, returns to 0 without serving and goes up to 14 and 37, 382. LOOK turns at 183 and comes down to 37 and 14, 299. C-LOOK jumps from 183 back to 14 and goes up to 37, 322
SCAN and C-SCAN run to the edge of the disk; LOOK and C-LOOK turn at the last request and save the trip.

LOOK and C-LOOK: turn at the last request

Running on to the edge when nothing is waiting there is wasted travel. LOOK is SCAN that turns around at the last request in its direction (183), and C-LOOK is C-SCAN that jumps back only as far as the lowest waiting request (14). Demo 5 (LOOK) travels 299 cylinders and Demo 6 (C-LOOK) 322. In practice "SCAN" and "C-SCAN" in an operating system usually mean these LOOK variants.

The totals

Demo 7 runs all six on the same queue and fills the totals panel. The starting direction matters for the four sweeping algorithms: switch head moving to down and run them again.

algorithmorder of stops (head moving up)total, uptotal, down
FCFS98, 183, 37, 122, 14, 124, 65, 67640640
SSTF65, 67, 37, 14, 98, 122, 124, 183236236
SCAN65, 67, 98, 122, 124, 183, (199), 37, 14331236
C-SCAN65, 67, 98, 122, 124, 183, (199), (0), 14, 37382386
LOOK65, 67, 98, 122, 124, 183, 37, 14299208
C-LOOK65, 67, 98, 122, 124, 183, 14, 37322326

There is no single winner. SSTF has the lowest total here but can starve; LOOK moving down beats it (208) because the two low requests are near the start. Some books do not count the return jump of C-SCAN and C-LOOK (it is a fast seek with no stops); then C-SCAN is 146 + 37 = 183 and C-LOOK 130 + 23 = 153. The page counts it, because the arm really travels.

Where this runs today

Linux keeps a request queue per disk and an I/O scheduler in the block layer. mq-deadline sorts requests by sector and serves them in one direction, like C-LOOK, but gives each request a deadline (500 ms for reads, 5 s for writes by default) so that none starves. bfq shares the disk fairly between processes. For SSDs the usual choice is none, because an SSD has no head and no seek: every block is equally close (see How an SSD Reads and Writes Data). A modern hard disk also reorders its own queue with NCQ, and it knows the platter's rotation as well, which the operating system does not (see How a Hard Disk Reads and Writes Data). The same trade-off between throughput and waiting time appears in CPU Scheduling, where SJF plays the role of SSTF and can starve long jobs.

Where mq-deadline sits on the way from write() to the disk, next to request merging and the NVMe queues, is shown in The Linux Block Layer: How a write() Reaches the Disk.

What the page leaves out

Real seek time is not linear in distance (the arm accelerates, coasts and settles, so a short seek costs much more per cylinder than a long one), rotational latency and transfer time, several platters and heads, reads vs writes, request merging, the anticipatory and deadline tricks of real schedulers, priorities, and decisions in the middle of a move: here the scheduler only chooses when the head reaches a stop.