June 24, 2026
Linux Scheduling Algorithms Explained: Understanding the Completely Fair Scheduler (CFS) (P2)
How Linux actually decides who gets CPU time — made beginner-friendly
By Alwinaji
4 min read
How Linux actually decides who gets CPU time — made beginner-friendly
In Part 1:
We learned:
The Linux scheduler decides what runs next
We explored:
Process lifecycle Context switching Time slicing Preemptive multitasking Why Linux feels responsive
But now comes the deeper question.
Imagine:
You run:
yes > /dev/nullyes > /dev/nullCPU usage:
100%100%Then:
You open:
vimvimQuestion:
Why does:
vimvimstill feel responsive?
Why doesn't:
yesyessteal all CPU forever?
How does Linux decide:
Who deserves more CPU time?
How does Linux balance:
Fairness
Responsiveness
PerformanceFairness
Responsiveness
Performancewithout chaos?
The answer is:
The Linux Scheduler Algorithm
And specifically:
CFS — Completely Fair Scheduler
Today we'll deeply understand:
Why Linux replaced old schedulers
What CFS actually is
Fair scheduling explained simply
vruntime (huge concept)
Red-black tree explained visually
Nice values (nice, renice)
Real-time scheduling basics
Hands-on labs
Observe scheduling live
And yes —
We'll keep it beginner-friendly.
Let's begin.
First: Why Linux Needed Better Scheduling
Imagine classroom.
Teacher says:
Everyone gets equal speaking time.Everyone gets equal speaking time.Nice.
But problem:
Some students:
Need more attentionNeed more attentionSome tasks:
Need faster responseNeed faster responseSome:
Can waitCan waitSimple scheduling:
Round-robinRound-robinwasn't enough.
Linux needed:
Fair
Responsive
Efficient
ScalableFair
Responsive
Efficient
Scalablescheduling.
Thus:
CFS (Completely Fair Scheduler)
was introduced.
Huge Linux innovation.
Old Scheduler Problem
Old Linux schedulers used:
Fixed time slices.
Example:
Process A → 10ms
Process B → 10ms
Process C → 10msProcess A → 10ms
Process B → 10ms
Process C → 10msSimple.
Problem:
Not smart.
Example:
Music appMusic appneeds low latency.
Background:
Compression taskCompression taskcan wait.
Treating them equally:
Bad responsivenessBad responsivenessLinux wanted smarter fairness.
What Is CFS?
Simple definition:
CFS tries to give every process a fair share of CPU time.
Key word:
Fair
But fairness does NOT mean:
Exactly equalExactly equalInstead:
Linux asks:
Who has gotten the least CPU recently?
Then chooses:
That process.
Beautiful idea.
Restaurant Analogy
Imagine restaurant.
Customers:
ProcessesProcessesWaiter:
SchedulerSchedulerQuestion:
Who gets served next?
CFS says:
Person who waited longest.Person who waited longest.Very fair.
No starvation.
No greedy customer wins forever.
Huge mental model.
The Big Mental Model
CFS tracks:
How much CPU each process already usedHow much CPU each process already usedThen:
Least CPU used
↓
Run firstLeast CPU used
↓
Run firstVisual:
Process A → 20ms used
Process B → 5ms used
Process C → 10ms used
Scheduler picks:
Process BProcess A → 20ms used
Process B → 5ms used
Process C → 10ms used
Scheduler picks:
Process BWhy?
Because:
Least CPU recentlyLeast CPU recentlyMind blown?
That's Linux fairness.
The Giant Concept: vruntime
This is:
The heart of CFS.
Question:
How does Linux measure fairness?
Using:
Virtual Runtime (
vruntime)
Simple definition:
How much CPU time process effectively received
Linux tracks:
CPU usage historyCPU usage historyfor every process.
Smaller:
vruntimevruntimemeans:
You ran less recentlyYou ran less recentlySo Linux says:
Your turn now.Your turn now.Huge concept.
Example of vruntime
Imagine:
Firefox → vruntime = 20
VS Code → vruntime = 10
Spotify → vruntime = 5Firefox → vruntime = 20
VS Code → vruntime = 10
Spotify → vruntime = 5Scheduler chooses:
SpotifySpotifyWhy?
Because:
Least CPU recentlyLeast CPU recentlyBeautiful fairness.
Visual Scheduling Flow
Smallest vruntime
↓
Scheduler picks
↓
Process runs
↓
vruntime increases
↓
Process waitsSmallest vruntime
↓
Scheduler picks
↓
Process runs
↓
vruntime increases
↓
Process waitsContinuous balancing.
Thousands of times per second.
The Red-Black Tree
Scary name, simple idea
Question:
How does Linux quickly find:
Smallest vruntimeSmallest vruntime?
Linux uses:
Red-Black Tree
Sounds terrifying.
Reality:
Organized sorting structure.
Think:
Processes sorted by fairnessProcesses sorted by fairnessLinux keeps:
Smallest vruntimeSmallest vruntimeat left side.
Example:
20
/ \
10 30
/
5 20
/ \
10 30
/
5Scheduler instantly finds:
55Fast.
Efficient.
Huge performance trick.
Why CFS Is Smart
CFS balances:
Fairness
Nobody starves.
Responsiveness
Interactive apps feel fast.
Throughput
Heavy work still progresses.
Scalability
Works on:
Laptop
Cloud
Servers
SupercomputersLaptop
Cloud
Servers
SupercomputersBeautiful engineering.
Hands-On Lab 1 — Observe Scheduling
Run:
toptopObserve:
CPU %
PR
NICPU %
PR
NIInteresting.
You're watching:
Scheduler decisions.
Live.
Nice Values Explained
Question:
Can we tell Linux:
This process matters lessThis process matters less?
Yes.
Using:
Nice values
Range:
-20 → highest priority
19 → lowest priority-20 → highest priority
19 → lowest priorityDefault:
00Important:
Lower:
nicenicemeans:
Higher priorityHigher priorityWeird Linux naming.
Hands-On Lab 2 — Low Priority Process
Run:
nice -n 10 yes > /dev/nullnice -n 10 yes > /dev/nullMeaning:
Less importantLess importantCheck:
toptopObserve:
NI = 10NI = 10Linux gives it:
Less CPU preferenceLess CPU preferenceVery cool.
Compare Priorities
Open terminal 1:
yes > /dev/nullyes > /dev/nullTerminal 2:
nice -n 15 yes > /dev/nullnice -n 15 yes > /dev/nullObserve:
toptopInteresting.
Normal process usually gets:
More CPUMore CPUHuge realization.
Linux scheduler listens.
Change Priority Live
Find PID:
ps aux | grep yesps aux | grep yesThen:
renice 15 PIDrenice 15 PIDLinux updates priority:
Live.
Very useful admin trick.
Process Priority Fields
In:
toptopLook for:
PR
NIPR
NIMeaning:
PR
Priority.
NI
Nice value.
Example:
PR = 20
NI = 0PR = 20
NI = 0Default process.
Why Interactive Apps Feel Fast
Question:
Why:
Typing in terminalTyping in terminalfeels instant?
CFS favors:
Interactive tasksInteractive tasksProcesses that:
Wake often
Sleep often
Need fast responseWake often
Sleep often
Need fast responseExample:
Terminal
Mouse
Keyboard
UITerminal
Mouse
Keyboard
UILinux tries:
Low latencyLow latencyHuge usability reason.
Real-Time Scheduling
Different world
Some workloads need:
Absolute priorityAbsolute priorityExamples:
Robotics
Audio
Industrial systemsRobotics
Audio
Industrial systemsLinux provides:
FIFO
Run until finished.
Round Robin
Take turns.
Danger:
Bad real-time process:
Can freeze systemCan freeze systemUsed carefully.
Hands-On Lab 3 — CPU Stress
Install:
sudo apt install stress-ngsudo apt install stress-ngRun:
stress-ng --cpu 4stress-ng --cpu 4Observe:
toptopWatch:
CPU balancingCPU balancingLinux distributing work.
Very cool.
Stop:
CTRL+CCTRL+CObserve Scheduler Live
Run:
htophtopPress:
F6F6Sort:
CPU %CPU %Watch priorities.
Observe:
Processes move dynamicallyProcesses move dynamicallyScheduler constantly adapting.
Common Beginner Misconceptions
1. "Fair means equal"
No.
Linux balances:
Needs
Priority
ResponsivenessNeeds
Priority
Responsiveness2. "Nice means more CPU"
Wrong.
Higher:
nicenicemeans:
Lower priorityLower priority3. "CPU % fixed forever"
Scheduler constantly adjusts.
Dynamic system.
4. "Background tasks never run"
Wrong.
CFS avoids starvation.
Everyone gets chance.
Mini Challenge
Question 1:
What is:
vruntimevruntime?
Question 2:
Why does:
vimvimremain responsive?
Question 3:
What does:
nice -n 10nice -n 10do?
Question 4:
Why does Linux use:
Red-black treeRed-black tree?
Think deeply.
The Big Mental Model
Linux CFS:
Track CPU usage
↓
Calculate vruntime
↓
Smallest vruntime wins
↓
Process runs
↓
Fairness maintainedTrack CPU usage
↓
Calculate vruntime
↓
Smallest vruntime wins
↓
Process runs
↓
Fairness maintainedBeautiful engineering.
Final Thoughts
At first:
CPU scheduling feels magical.
Apps stay responsive.
Background tasks continue.
Everything feels smooth.
But underneath?
Linux is constantly asking:
Who got CPU recently?
Who waited longest?
Who deserves next turn?Who got CPU recently?
Who waited longest?
Who deserves next turn?And that hidden fairness engine is called:
CFS — Completely Fair Scheduler
And once this clicks…
You stop seeing scheduling as magic.
You finally understand:
How Linux actually shares CPU fairly.