What Is the Linux Scheduler Class Hierarchy? – Best Linux Device Drivers Course

« Previous Lecture | Next Lecture »

Linux CPU Scheduler Explained: Scheduling Classes and Policies (Updated for Modern Kernels)

Part 1 of our free Linux kernel development course — understand how the Linux CPU scheduler decides which thread runs next

The Linux CPU scheduler is the piece of kernel code that answers one deceptively simple question millions of times per second: which thread should run on this CPU right now? In this lesson of our free Linux kernel development course, you will learn how the Linux CPU scheduler is organized internally, what scheduling classes and scheduling policies are, and how modern kernels (6.6 and newer, including the current 7.x series) pick the next task to run.

This tutorial is part of EmbeddedPathashala’s free Linux kernel programming course and free embedded systems course. Everything here reflects the scheduler as it exists in today’s kernels — including the EEVDF fair scheduler and the new sched_ext class — not the older CFS-only description you will find in many books.

What You Will Learn

  • Why the thread (not the process) is the unit of scheduling in Linux
  • The modular scheduling-class architecture of the Linux CPU scheduler
  • All the scheduling policies: SCHED_OTHER, SCHED_BATCH, SCHED_IDLE, SCHED_FIFO, SCHED_RR, SCHED_DEADLINE, and the new BPF-based sched_ext
  • How the kernel walks the class hierarchy to pick the next task
  • What changed in kernel 6.6 (EEVDF) and kernel 6.12 (sched_ext)

Prerequisites

  • Basic C programming and comfort with the Linux command line
  • Understanding of processes and threads (covered earlier in this free Linux kernel development course)
  • Any Linux machine or virtual machine — kernel 6.6 or newer recommended

The Thread Is What Gets Scheduled

A common beginner mistake is thinking Linux schedules processes. It does not. On Linux, the kernel schedulable entity (KSE) is the thread. A process is simply a container: it holds the address space, open files, and credentials, while its threads are the actual units of execution that compete for CPU time. A single-threaded process is just a process with exactly one schedulable thread.

Every thread carries two scheduling attributes, assigned per thread, not per process:

  • A scheduling policy — the algorithm that governs it
  • A priority — either a nice value (for normal threads) or a real-time priority (for real-time threads)

The default for every new thread is SCHED_OTHER (also called SCHED_NORMAL) with real-time priority 0 and nice value 0.

Linux CPU Scheduler Architecture: Scheduling Classes

The Linux CPU scheduler is not one giant algorithm. Since kernel 2.6.23 it has been modular: the core scheduler (kernel/sched/core.c) knows nothing about fairness, deadlines, or time slices. Instead, it delegates to a chain of scheduling classes, each implementing its own algorithm behind a common interface (a structure of function pointers such as enqueue_task, dequeue_task, and pick_task).

When a CPU needs a new task, the core scheduler walks the classes in strict priority order and asks each one: “do you have a runnable task?” The first class that answers yes wins. This means a runnable real-time thread will always be chosen before any normal thread.

Scheduling Class Hierarchy in Modern Linux (Kernel 6.12+)
Core Scheduler (kernel/sched/core.c) — asks each class in order ↓
1. stop_sched_class Highest priority. Kernel-internal only (CPU hotplug, migration). Userspace can never use it.
2. dl_sched_class Deadline tasks: SCHED_DEADLINE (runtime / deadline / period model)
3. rt_sched_class Real-time tasks: SCHED_FIFO and SCHED_RR (priorities 1–99)
4. fair_sched_class Normal tasks: SCHED_OTHER, SCHED_BATCH, SCHED_IDLE. Algorithm: EEVDF (was CFS before kernel 6.6)
5. ext_sched_class sched_ext (kernel 6.12+): custom schedulers written as BPF programs (SCHED_EXT)
6. idle_sched_class The per-CPU idle thread (swapper). Runs only when nothing else is runnable.

Note: the exact position of ext_sched_class relative to the fair class can depend on kernel configuration, but conceptually it sits alongside/below the fair class and above idle. The key idea to remember for interviews: classes are consulted in fixed priority order, and stop > deadline > RT > fair > idle always holds.

Scheduling Policies in the Linux CPU Scheduler

Each scheduling class implements one or more policies that userspace can select. Here is the complete, up-to-date map:

Policy Class Priority Range Typical Use
SCHED_OTHER fair (EEVDF) nice −20 to +19 Default. Almost everything: shells, browsers, daemons
SCHED_BATCH fair (EEVDF) nice −20 to +19 CPU-heavy batch jobs; treated as less interactive
SCHED_IDLE fair (EEVDF) (nice ignored) Extremely low importance work (indexers, background scans)
SCHED_FIFO rt RT prio 1–99 Run-to-completion real-time; no time slicing
SCHED_RR rt RT prio 1–99 Real-time with round-robin time slices among equal priority
SCHED_DEADLINE dl runtime/deadline/period Periodic hard-deadline work (audio pipelines, control loops)
SCHED_EXT ext (6.12+) defined by BPF scheduler Custom schedulers (gaming, datacenter experiments)

What Changed in Modern Kernels: CFS → EEVDF and sched_ext

If you learned Linux CPU scheduling from books written before 2023, two big updates matter:

1. EEVDF replaced the CFS pick logic (kernel 6.6, October 2023)

The Completely Fair Scheduler (CFS) drove SCHED_OTHER threads from kernel 2.6.23 to 6.5. Since kernel 6.6, the fair class uses EEVDF (Earliest Eligible Virtual Deadline First). The fair class, its file kernel/sched/fair.c, and much of the surrounding machinery (load weights, cgroup support) remain — but the decision of which fair task runs next is now deadline-based rather than “smallest vruntime wins”. We cover EEVDF in depth in the next lecture of this free Linux kernel programming course.

2. sched_ext arrived (kernel 6.12, late 2024)

sched_ext is a new scheduling class whose behavior is supplied at runtime by a BPF program. This lets developers experiment with completely custom scheduling algorithms — without patching or rebuilding the kernel — and safely fall back to the default scheduler if the BPF scheduler ever misbehaves. Valve’s SteamOS-related work and datacenter operators have been early adopters.

How the Scheduler Picks the Next Task: The Big Picture

Pick-Next-Task Flow (simplified)
Scheduling point reached (timer tick, task sleeps/wakes, syscall return, preemption)
↓
Core scheduler runs schedule() → asks classes top-down: stop → deadline → rt → fair → ext → idle
↓
First class with a runnable task returns it → context switch to that task
↓
If no class has anything runnable → per-CPU idle thread runs

Because most systems run few or no real-time tasks, in practice the fair class answers the question the vast majority of the time. That is why the fair scheduler (CFS historically, EEVDF today) gets so much attention in any Linux kernel development course.

Quick Hands-On: See Scheduling Classes on Your System

You can observe policies right now. Every thread exposes its policy through /proc:

# Show the scheduling policy number of PID 1 (field 41 of /proc/PID/stat)
awk '{print "policy number:", $41}' /proc/1/stat

# Human-readable details for any thread
grep -E "policy|prio" /proc/1/sched

Policy numbers map as: 0 = SCHED_OTHER, 1 = SCHED_FIFO, 2 = SCHED_RR, 3 = SCHED_BATCH, 5 = SCHED_IDLE, 6 = SCHED_DEADLINE, 7 = SCHED_EXT. In the third lecture of this series we build a complete tool around chrt and ps to query every thread on the system.

Common Mistakes and Interview Traps

  • “Linux schedules processes” — wrong; it schedules threads (KSEs).
  • “Higher nice value means higher priority” — wrong; nice +19 is the lowest normal priority, nice −20 the highest.
  • “CFS is the current Linux scheduler” — outdated; since kernel 6.6 the fair class uses EEVDF.
  • “Real-time priority applies to SCHED_OTHER threads” — no; normal threads always report RT priority 0. Their weight comes from the nice value.
  • Setting SCHED_FIFO priority 99 on a busy-looping thread — this can starve the whole CPU. Kernels reserve a small RT bandwidth safety margin, but it is still a classic self-inflicted lockup.

Best Practices

  • Leave threads on SCHED_OTHER unless you have a measured latency requirement.
  • Prefer SCHED_DEADLINE over FIFO/RR for periodic real-time work — it lets the kernel do admission control.
  • Use SCHED_IDLE or SCHED_BATCH for background jobs on embedded devices to protect the UI/main loop.
  • On embedded Linux, audit RT threads with the querying techniques from lecture 3 — rogue vendors sometimes ship drivers with unjustified RT priorities.

Key Takeaways

  • The Linux CPU scheduler schedules threads, each with a per-thread policy and priority.
  • The scheduler is modular: fixed-priority scheduling classes (stop > deadline > rt > fair > ext > idle) hide different algorithms behind one interface.
  • Since kernel 6.6, the fair class runs EEVDF; since 6.12, sched_ext enables BPF-defined custom schedulers.
  • The default policy everywhere is SCHED_OTHER with RT priority 0.

Conclusion

You now have the modern mental model of the Linux CPU scheduler: a small, algorithm-agnostic core that consults scheduling classes in strict priority order, with the EEVDF-powered fair class doing most of the day-to-day work. This architecture is exactly why Linux could swap CFS for EEVDF, and later add sched_ext, without disturbing real-time or deadline scheduling. In the next lecture of this free Linux kernel development course, we go inside the fair class and understand how EEVDF actually chooses among normal threads — eligibility, lag, and virtual deadlines made simple.

FAQ

What is the Linux CPU scheduler?

It is the kernel subsystem that decides which runnable thread executes on each CPU and for how long. It is modular, built from priority-ordered scheduling classes.

Which scheduler does Linux use today?

For normal threads, modern kernels (6.6 and later, including the current 7.x series) use EEVDF inside the fair scheduling class. Real-time threads use the RT and deadline classes, and kernel 6.12+ optionally supports BPF-based custom schedulers via sched_ext.

Is CFS still used in Linux?

The fair scheduling class and its source file remain, but the task-selection algorithm was changed from CFS’s smallest-vruntime rule to EEVDF’s earliest-eligible-virtual-deadline rule in kernel 6.6.

What is the default scheduling policy in Linux?

SCHED_OTHER (also called SCHED_NORMAL) with real-time priority 0 and nice value 0.

What is the difference between SCHED_FIFO and SCHED_RR?

Both are real-time policies with priorities 1–99. FIFO tasks run until they block, yield, or are preempted by higher priority; RR adds a time slice so equal-priority RT tasks rotate.

What is sched_ext?

A scheduling class merged in kernel 6.12 that lets you load a custom CPU scheduler as a BPF program at runtime, with automatic fallback to the default scheduler on error.

Does a process or a thread get scheduled in Linux?

The thread. Scheduling policy and priority are per-thread attributes; two threads of the same process can run under different policies.

Where is this free Linux kernel development course going next?

Lecture 2 covers the EEVDF fair scheduler internals, and lecture 3 shows practical querying of any thread’s policy and priority with chrt, ps, and C code.

Continue the free Linux kernel programming course on EmbeddedPathashala

« Previous Lecture Next Lecture »

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *