skip to content

questions

6

On Linux, what does a process's nice value control, what range can it take, and why can an ordinary user raise a process's nice value but not lower it again?

level: juniorimportance: must knowfreq 62%

answer

  1. a hint, not a reservation
  2. lower number wins the CPU
  3. the range is asymmetric around zero
  4. giving away is free, taking back is not
  5. CAP_SYS_NICE and RLIMIT_NICE

basics

~20 s

A nice value biases how much CPU a Linux task gets when CPUs are contended. It runs from -20 (most favoured) to 19 (least favoured), default 0. Lowering it needs privilege, so an unprivileged renice is a one-way trip.

solid answer

~50 s

The nice value is a per-thread hint to the Linux scheduler about how much CPU weight a task deserves relative to everything else competing for the same CPU. It runs from **-20** (most favoured) through **0** (the default a shell inherits) to **19** (least favoured), and you set it either at launch with `nice -n 10 cmd` or on a running task with `renice -n 10 -p PID`. The important asymmetry is that raising your own nice value — giving CPU away — is always allowed, while lowering it, or renicing somebody else's process, requires the `CAP_SYS_NICE` capability (in practice, root); an unprivileged user's ceiling is set by the `RLIMIT_NICE` resource limit. And nice only matters under contention: on a box with idle CPUs, a nice 19 task runs at full speed, because there is nothing to take time from it.

code

bash · 8 lines
bash
# start a batch job de-prioritised
nice -n 10 ./nightly-report.sh

# raise an existing process's nice value: always allowed for your own process
renice -n 15 -p 4242

# lower it again: fails for an unprivileged user
renice -n 0 -p 4242

go deeper

for a junior

Be ready to state the range (-20 to 19), say plainly that lower means more favoured, and show both nice at launch and renice on a running PID.

for a middle

Explain that nice is a weight applied only under contention, that it is per-thread on Linux, and that raising it is unprivileged while lowering it needs CAP_SYS_NICE within RLIMIT_NICE.

for a senior

Show judgment about when nice is the wrong tool: it gives no isolation, no I/O effect, and no protection from cache or memory-bandwidth contention on a busy host.

for a principal

Own the policy angle — who is allowed negative nice on shared hosts, why handing out CAP_SYS_NICE broadly is a noisy-neighbour hazard, and when priority hints should be replaced by hard resource controls.

## What a nice value actually is Every schedulable entity on Linux carries a *nice value*, a small integer that tells the kernel's fair-share scheduler how much CPU weight this task should get relative to other tasks competing for the same CPU. It is not a guarantee, not a reservation and not a real-time priority — it is a bias applied when more work is runnable than there are CPUs to run it. The range is **-20 to 19** inclusive. Lower is *better*: -20 is the most favoured, 19 the least, and 0 is the default that a process inherits from its parent, which for anything you type is your shell. The counter-intuitive direction is the standard exam trap — a "nicer" process is one that is nice *to others*, so a high nice value means it steps aside. ## Setting it Two tools cover almost all use: ```bash nice -n 10 ./nightly-report.sh # launch a new process with nice 10 renice -n 10 -p 4242 # change an already-running PID renice -n 5 -u builduser # change every process of a user ``` Underneath, both go through the `setpriority(2)` system call (`nice(2)` is the older single-argument form). One Linux-specific detail that surprises people who learned Unix elsewhere: on Linux the nice value is a **per-thread attribute**, not a per-process one, even though `setpriority(PRIO_PROCESS, ...)` reads as though it applies to the process. Two threads of the same process can carry different nice values. ## Why the change is one-way for ordinary users Giving CPU away is harmless, so any user may raise the nice value of their own processes without restriction. Taking CPU back is a privilege operation, because it lets you gain time at the expense of every other user on the machine. Concretely: - Lowering a nice value (towards -20) requires the `CAP_SYS_NICE` capability, which normally means root. - Renicing a process you do not own also requires `CAP_SYS_NICE`. - An unprivileged process's floor is governed by the `RLIMIT_NICE` resource limit; the limit is expressed as `20 - nice`, so the default of 0 means "cannot go below nice 0 at all". Raise it (via PAM limits or `ulimit`) and the user gains room to lower nice down to that floor. So `renice -n 15 -p $$` works for anyone, and the same user cannot then run `renice -n 0 -p $$` to undo it. This is a frequent operational surprise: an operator lowers the priority of a batch job to calm a busy machine, and then needs root to restore it. ## Why nice cannot make a process faster The scheduler distributes CPU time that is *contested*. If your 8-CPU machine has three runnable tasks, all three run whenever they want, and their nice values change nothing measurable. `nice -n -20 ./thing` does not make `./thing` compute faster — it only wins arguments that were already happening. Conversely, running a backup at nice 19 does not stop it hammering the disk; nice is a **CPU** knob, and I/O priority is a separate mechanism entirely. The same reasoning explains why nice is weak protection for a latency-sensitive service. A favoured task still waits for a CPU that is currently executing a kernel critical section, still queues behind interrupts, and still contends for memory bandwidth and last-level cache with everything else on the socket. Nice moves the CPU-share needle; it does not create isolation. ## Where it shows up when you look The nice value of a task is visible in `/proc/<pid>/stat` (the 19th field) and in the standard process listing columns. The related "priority" number a listing shows for a normal task is derived from the nice value, which is why an ordinary nice 0 task and a real-time task look so different there — they are scheduled by different policies, and only normal tasks use nice at all. ## What an interviewer is checking Three things, in order: that you know the direction and the range without hedging; that you know an unprivileged user can only ever give CPU away; and that you do not oversell it — nice is a proportional-share hint that means nothing on an uncontended machine and nothing at all for disk or network work.

  • If a machine has more idle CPUs than runnable tasks, what measurable difference does a nice value make?
    None. The fair-share scheduler only redistributes contested CPU time, so with spare CPUs every runnable task runs whenever it wants and a nice 19 task finishes as quickly as a nice -20 one. Nice values become visible only once runnable tasks outnumber CPUs and the scheduler has to choose between them.
  • A team runs a nightly backup at nice 19 and it still slows the database down. What did they misunderstand?
    Nice is a CPU-share knob only. A backup is dominated by disk reads and page-cache pressure, none of which the nice value touches. They would need I/O priority (ionice with a scheduler that honours it), block-layer or cgroup I/O throttling, or simply rate-limiting the backup tool — CPU de-prioritisation was never going to help.
  • How would you let a specific service account start processes at a negative nice value without giving it root?
    Raise its RLIMIT_NICE, typically via a PAM limits configuration or the service's unit configuration, since the limit encodes the floor as 20 minus the nice value. Alternatively grant just CAP_SYS_NICE to the specific binary or service rather than full root — both approaches keep the privilege scoped to CPU priority instead of everything else.

saying these in an interview costs you the question

  • Says a lower nice value means lower priority
  • Claims nice makes a process run faster on an idle box
  • Thinks nice also prioritises disk or network I/O
  • Believes any user can renice their own process back to 0
  • States the range is 0 to 19 or 1 to 99

context

open as a page

A Linux server with 8 CPUs shows a 1-minute load average of 30, yet CPU utilisation is near idle. What does Linux's load average actually count, and what does this combination point to?

level: middleimportance: must knowfreq 68%

basics

~20 s

Linux counts both runnable tasks and tasks in uninterruptible sleep (D state) in its load average, unlike traditional Unix. High load with idle CPUs therefore means processes are blocked in the kernel waiting on storage or a hung mount, not competing for CPU.

open as a page

You pin a latency-sensitive Linux process to CPUs 2 and 3 with taskset. Does that reserve those CPUs for it, and what happens to the affinity when the process forks or calls exec?

level: middleimportance: should knowfreq 35%

basics

~20 s

Setting CPU affinity restricts where a task may run; it does not reserve anything. Every other task on the system can still be scheduled onto CPUs 2 and 3. Children inherit the mask across fork, and it survives exec.

open as a page

How does Linux's fair-share CPU scheduler (CFS, and EEVDF since kernel 6.6) turn a task's nice value into an actual share of CPU time?

level: middleimportance: should knowfreq 45%

basics

~20 s

Linux maps each nice value to a weight, roughly 1.25x per step with nice 0 at 1024, and hands every runnable task CPU time in proportion to its weight. Each nice step therefore shifts about 10% of the contested CPU.

open as a page

What do the Linux real-time scheduling policies SCHED_FIFO and SCHED_RR change about how a thread is scheduled, and what can a runaway SCHED_FIFO thread do to the machine?

level: seniorimportance: should knowfreq 33%

basics

~20 s

SCHED_FIFO and SCHED_RR give a thread a static priority of 1-99 that preempts every normal task; FIFO runs until it blocks or yields, RR adds a time slice between equal priorities. A runaway FIFO loop starves everything below it, which is why Linux throttles real-time tasks by default.

open as a page

What do the Linux I/O scheduling classes set by ionice (realtime, best-effort, idle) do, and why can running a backup under `ionice -c 3` have no effect at all?

level: seniorimportance: nice to knowfreq 22%

basics

~20 s

ionice tags a process's block-layer requests with an I/O class and level, so a lower-priority job yields disk service to others. It only works if the active I/O scheduler honours those tags — with the none scheduler common on NVMe, the tag is simply ignored.

open as a page