Process priority

On this page 7

Process priority in Linux is the value the kernel scheduler uses to decide which runnable task receives the CPU next and how large a share of CPU time it gets when several tasks compete. Among Linux processes, priority is not a single number but a combination of the scheduling policy, the nice value for ordinary tasks and the real-time priority for time-critical tasks.

Priority only matters under contention. On an idle core, a task with the lowest possible priority runs at full speed; the setting decides who yields when demand exceeds the available CPU capacity. Closely related controls such as nice, CPU affinity and cgroups shape the same decision from different angles.

How the Linux scheduler uses process priority

The kernel keeps one unified priority scale from 0 to 139, where a lower internal number means a more important task. Values 0 to 99 belong to real-time tasks, and values 100 to 139 belong to normal tasks, which map directly to nice values from -20 to 19 (internal priority = 120 + nice).

The two halves of the scale behave very differently. A runnable real-time task always preempts every normal task on the same CPU, regardless of nice values. Among normal tasks there is no strict ordering: the fair scheduler (CFS, replaced by EEVDF in kernel 6.6) gives every task a weight derived from its nice value and divides CPU time in proportion to those weights.

The following table shows how one task’s priority appears in the kernel, in the tools administrators use and in the scheduling class it implies.

Task typeUser-facing valueKernel internal priorityValue in top (PR)
Real-time, highestrtprio 990rt
Real-time, lowestrtprio 198-2
Normal, highestnice -201000
Normal, defaultnice 012020
Normal, lowestnice 1913939
Priority ranges across kernel and user-space views

The opposite directions confuse many administrators: for real-time priority a higher number wins, while for nice a lower number wins. The internal scale reconciles both by inverting the real-time value (internal = 99 – rtprio).

Scheduling policies and their priority models

The scheduling policy determines which kind of priority a task has and how the scheduler interprets it. Every Linux thread has exactly one policy, and policies are set per thread, not per process.

PolicyPriority parameterBehaviorTypical use
SCHED_DEADLINERuntime, deadline, periodEarliest deadline first, above all real-time tasksPeriodic control loops
SCHED_FIFOrtprio 1-99Runs until it blocks or yieldsAudio, industrial I/O
SCHED_RRrtprio 1-99Like FIFO, with time slices among equal prioritiesSeveral equal real-time workers
SCHED_OTHERNice -20 to 19Weighted fair sharingAlmost all processes
SCHED_BATCHNice -20 to 19Fair sharing, treated as CPU-boundCompilation, batch jobs
SCHED_IDLENone (very low weight)Runs only on otherwise idle CPUBackground indexing
Linux scheduling policies compared

Real-time policies carry real risk. A SCHED_FIFO loop that never blocks can starve every normal task on its CPU, so the kernel reserves time through real-time throttling: by default sched_rt_runtime_us is 950000 of a 1000000 microsecond period, leaving 5% of each second for normal tasks.

How nice values translate into CPU share

Each nice step changes a task’s weight by a factor of about 1.25, which the kernel designers chose so that one step shifts roughly 10% of CPU time between two competing tasks. The weight of nice 0 is 1024, and the full table runs from 88761 at nice -20 down to 15 at nice 19.

The table below shows the resulting CPU split when exactly two CPU-bound tasks share one core, one of them at the default nice 0. The share is computed as the task’s weight divided by the sum of both weights.

Nice of second taskWeight of second taskShare of nice 0 taskShare of second task
-5312124.7%75.3%
0102450.0%50.0%
182055.5%44.5%
533575.3%24.7%
1011090.3%9.7%
191598.6%1.4%
CPU share of two competing tasks on one core

The key point is that nice is relative, not absolute. A nice 19 task alone on a core still receives 100% of it, and two nice 10 tasks split a core evenly, exactly like two nice 0 tasks. Only the ratio between competing weights matters.

Setting and inspecting process priority

Administrators change priority with a small set of standard tools, and unprivileged users can only lower priority. Raising it, meaning a lower nice value or any real-time policy, requires CAP_SYS_NICE or an appropriate RLIMIT_NICE or RLIMIT_RTPRIO resource limit.

Tool or settingWhat it controlsExample
niceNice value at startnice -n 10 make -j8
reniceNice value of a running processrenice -n 5 -p 4321
chrtPolicy and real-time prioritychrt -f -p 50 4321
ioniceDisk I/O class and levelionice -c 3 -p 4321
systemd unitPersistent service priorityNice=, CPUSchedulingPolicy=
ps and topInspectionps -eo pid,cls,ni,rtprio,comm
Tools for managing process priority

I/O priority is a separate dimension. The ionice best-effort class has levels 0 to 7, and when none is set the kernel derives it from the nice value as (nice + 20) / 5, so nice 0 maps to level 4. Whether the setting has any effect depends on the block I/O scheduler: BFQ honors it fully, while none ignores it.

Limitations and common mistakes

Most priority problems come from expecting priority to fix a bottleneck that is not CPU time. Nice does not limit memory, disk or network usage, and it cannot make a task faster than an idle CPU already allows.

  • Autogroup scheduling on many desktop kernels groups tasks by session, so renicing a process only affects it relative to its own session, not to other terminals.
  • Cgroup CPU weights (cpu.weight, default 100) apply between groups first; a nice -20 task inside a low-weight container can still lose to a nice 0 task elsewhere.
  • Priority inversion occurs when a high-priority task waits on a lock held by a low-priority one; Linux mitigates it with priority inheritance on PI-aware mutexes.
  • Assigning rtprio 99 to application threads is a common error, because it competes with kernel threads such as migration and watchdog tasks.
  • Because nice is a per-thread attribute in Linux, renicing a PID can change only the main thread while existing worker threads keep their old value.

Put simply

A computer usually has more programs wanting the processor than it has processor cores. Process priority is the rule that decides who goes first and who gets a bigger slice of time when everyone is waiting.

Think of a busy kitchen with one stove. Ordinary dishes take turns, and a dish marked as more important simply gets longer turns. A few emergency orders skip the line entirely. In Linux, the nice value sets the turn length for ordinary programs, and real-time priority marks the emergency orders. When the stove is free, every dish cooks at full speed regardless of its label.

In practice

A build server with 16 cores runs a web dashboard for developers and nightly compilation jobs that use every core for about two hours. During the build, the dashboard becomes slow because its few request threads compete equally with dozens of compiler processes.

The administrator starts the build through a systemd unit with Nice=15 and IOSchedulingClass=idle. At nice 15 each compiler process has a weight of 36 against 1024 for the dashboard threads, so on a contested core a dashboard thread receives about 97% of the time it asks for. The dashboard’s response time returns to normal, while the build still finishes in almost the same time, because the dashboard uses only a small fraction of total CPU capacity.