103.6 Modify process execution priorities¶
Weight: 2
Candidates should be able to manage process execution priorities.
Objectives
- Know the default priority of a job that is created.
- Run a program with higher or lower priority than the default.
- Change the priority of a running process.
Terms
nice, ps, renice, top
On a Linux machine, you might have hundreds of processes running at the same time and competing for more CPU and RAM. The good news is that you can give some of the processes higher or lower priority, or nice-ness, in this competition. Let's have a look at a sample top output:
$ top
Tasks: 169 total, 1 running, 168 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 3.0 sy, 0.0 ni, 97.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 5948.9 total, 4115.2 free, 438.2 used, 1395.5 buff/cache
MiB Swap: 975.0 total, 975.0 free, 0.0 used. 5210.3 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6496 nagato 20 0 10112 3704 3212 R 6.2 0.1 0:00.01 top
1 root 20 0 165172 10576 7780 S 0.0 0.2 0:02.80 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.09 kthreadd
3 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_gp
4 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 rcu_par_gp
6 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 kworker/0:0H-events_highpri
8 root 0 -20 0 0 0 I 0.0 0.0 0:12.71 kworker/0:1H-events_highpri
9 root 0 -20 0 0 0 I 0.0 0.0 0:00.00 mm_percpu_wq
10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_rude_
11 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_tasks_trace
The NI column shows how nice this process is. The nicer the process, the less CPU it asks for. The nice values can be from -20 to 19. To interpret this value, look at it like this: a process with nice = -20 is ANGRY and gets more priority for CPU and RAM, while a process with nice = 19 is SUPER NICE and lets other processes use the resources before it.
Look at the two columns together in that output. Most processes show PR 20 NI 0. The kernel workers show PR 0 NI -20, which is the angry end of the scale. Those are jobs the kernel wants handled immediately.
The scale, drawn out:
-20 ................ 0 ................ 19
| | |
angry the default super nice
takes CPU gives CPU away
first to everyone else
only root can go below 0
Why the scheduler needs this at all: only one process can hold the CPU at a time. Linux is preemptive, which means the kernel can take the CPU away from a running process and hand it to a more important one, even if that process did not ask to give it up. The scheduler decides who goes next, and the nice value is one of the inputs to that decision.
Scheduling comes in two kinds. Real-time processes are scheduled strictly by priority and always outrank normal ones. Normal processes are everything else, including all your programs, and those are the only ones the nice value affects.
Underneath the nice value there is a second number, the static priority. Linux reserves priorities 0 to 99 for real-time processes and 100 to 139 for normal ones. Lower means more important. You can read it straight from /proc:
PID 1 is systemd, and 120 is the standard priority for a normal process. That is why the range around it runs from 100 to 139.
The confusing part is that ps and top each display this number differently:
real value in /proc/PID/sched 120
ps -el PRI column 80 (add 40 to get 120)
top PR column 20 (0 to 39 range)
ps shows priorities from -40 to 99 for historical reasons, so add 40 to get the real number. top shifts real-time priorities into negative numbers, or shows rt, which makes them easy to spot at a glance.
The default value for nice is normally set to 0. This can be checked with:
You can also check the nice-ness using the ps command:
$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 15044 15035 0 80 0 - 7453 wait pts/29 00:00:00 bash
0 S 1000 15052 15044 0 60 -20 - 3976 hrtime pts/29 00:00:00 sleep
0 R 1000 15080 15044 0 80 0 - 4680 - pts/29 00:00:00 ps
Compare the PRI and NI columns on the middle line. That sleep has NI -20 and PRI 60, while the normal processes have NI 0 and PRI 80. Lowering the nice value by 20 lowered the priority number by 20 as well. The two move together, which is what "nice affects priority" means in practice.
Two more ways to list priorities. ps -Al or ps -el shows every process on the system:
$ ps -el
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 9292 - ? 00:00:00 systemd
4 S 0 19 1 0 80 0 - 8817 - ? 00:00:00 systemd-journal
4 S 104 61 1 0 80 0 - 64097 - ? 00:00:00 rsyslogd
4 S 0 63 1 0 80 0 - 7244 - ? 00:00:00 cron
1 S 0 126 1 0 80 0 - 4031 - ? 00:00:00 dhclient
4 S 0 154 1 0 80 0 - 3937 - pts/0 00:00:00 agetty
4 S 0 160 1 0 80 0 - 16377 - ? 00:00:00 sshd
4 S 0 280 0 0 80 0 - 5301 - ? 00:00:00 bash
0 R 0 392 280 0 80 0 - 7221 - ? 00:00:00 ps
And you can pick your own columns, which is useful for finding the heaviest processes:
Reading that: -o chooses the columns, --sort=-pcpu sorts by CPU percentage descending, and head keeps only the top ten.
Setting nice-ness¶
If you need to change the niceness level of a program you can run it with the nice command and the -n switch (for nice):
$ nice -n 19 echo "I am running!"
I am running!
$ nice -n -20 echo "I am running!"
nice: cannot set niceness: Permission denied
I am running!
$ sudo nice -n -20 echo "I am running!"
I am running!
As you can see in the above example, only root can issue high-priority niceness, below 0.
Look closely at the second command. It printed an error and still ran. nice could not set the priority, so it gave up on that part and ran the command at the normal priority anyway. It did not refuse the whole job.
If you run a command with nice without -n, the default will be -n 10.
$ nice xeyes &
[1] 15217
$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 15044 15035 0 80 0 - 7455 wait pts/29 00:00:00 bash
0 S 1000 15217 15044 0 90 10 - 12522 poll_s pts/29 00:00:00 xeyes
0 R 1000 15218 15044 0 80 0 - 4680 - pts/29 00:00:00 ps
That proves the default. xeyes was started with plain nice and no number, and it shows NI 10, with PRI raised from 80 to 90 to match.
The rule about who may do what is worth stating plainly, because it is easy to get backwards:
normal user can only RAISE the nice value 0 -> 19
(make a process nicer, lower priority)
and cannot lower it again afterwards
root can set anything -20 -> 19
A normal user lowering priority is safe, since it only gives resources away. Raising priority takes resources from everyone else, which is why it needs root.
Real world use for nice -n 19: running a big backup or compression job on a busy server:
The archive still gets made, but it steps aside whenever anything else needs the CPU, so users do not notice the server slowing down.
Changing priorities¶
The renice command can be used to change the niceness of your running processes, or others if you are root:
$ ps -ef | grep firefox
nagato 13605 11226 30 08:28 ? 00:10:13 /usr/lib/firefox/firefox
nagato 15192 15044 0 09:01 pts/29 00:00:00 grep firefox
$ sudo renice -n -10 13605
13605 (process ID) old priority 5, new priority -10
You can also press r in the top command to renice a process.
Note the two step pattern there. ps -ef | grep first, to find the PID, then renice on that number. renice works on a running process, so it always needs a PID, a group or a user, never a command name.
The -p form gives the same output message:
Two more options change many processes at once:
-gapplies to every process owned by a group-uapplies to every process owned by a user
So renice +5 -g users raises the nice value of every process belonging to the users group by five.
Real world use for renice -u: a shared build server where one developer's jobs are starving everyone else. renice +10 -u bob pushes all of that user's processes down in one command, without having to hunt for each PID.
The top route: press r on the main screen and it asks which process:
Type the PID and press Enter, then it asks for the new value with Renice PID 1 to value. This is the same job as renice, done inside the live display.
Summary¶
I have a Linux system where far more processes exist than there are CPUs, so the kernel's scheduler decides who runs next. Linux is preemptive, which means it can take the CPU away from a running process and hand it to a more important one without waiting to be asked. Most of my programs run under the normal scheduling policy, and those are the ones I can influence.
The number I actually change is the nice value. It runs from -20 to 19, and the default for every new process is 0. A low number means the process is demanding and gets the CPU sooner, a high number means it is polite and lets others go first. Underneath that sits the static priority, which I can read as prio in /proc/PID/sched and which normally shows 120. Both ps and top display that same number differently, ps in the PRI column where I add 40 to get the real value, and top in the PR column where real-time processes appear as negative or as rt.
To start something at a different priority I use nice. With -n I pick the value, and without it the default is 10. To change something already running I use renice with a PID, or -g for a whole group and -u for a whole user. I can also do it live by pressing r inside top. Both ps -l and top show me the current NI column so I can check the result.
The permission rule is the part I have to keep straight. Any user can make their own process nicer by raising the number, but only root can lower it below zero, because lowering it takes CPU away from everything else on the machine. That is also why nice -n -20 as a normal user prints a permission error and then runs the command anyway at the normal priority, rather than refusing outright.