RHCSA Rapid Track
Course update
An updated version of this course is available that uses a newer version of Red Hat Enterprise Linux in the lab environment. Therefore, the RHEL 9.0 version of the lab environment will retire on December 31, 2024. Please complete any work in this lab environment before it is removed on December 31, 2024. For the most up-to-date version of this course, we recommend moving to the RHEL 9.3 version.
Modern computer systems use multi-core, multi-thread CPUs that can execute many instruction threads simultaneously. The largest high-performing supercomputers can have hundreds or thousands of CPUs with hundreds of processing cores and thread structures per CPU, and can process millions of instruction threads in parallel. Although a single user who runs many applications can saturate the typical desktop system or personal workstation with CPU activity, a correctly sized and configured workstation is designed to match the user's intended workload. However, the typical enterprise or internet server handles many hundreds or thousands of users and application requests each second, which can result in CPU saturation. All systems under CPU load experience scenarios that require handling more process threads than the available system CPU processing units to schedule the threads immediately.
Linux and other operating systems use a technique called time-slicing or multitasking for process management. The operating system process scheduler rapidly switches between process threads on each available CPU core. This behavior gives the impression that many processes are running at the same time.
Process priority sets the importance of each process.
Linux implements scheduling policies that define the rules by which processes are organized and prioritized to obtain CPU processing time.
The various Linux scheduling policies might be designed to handle interactive application requests, or non-interactive batch application processing, or real-time application requirements.
Real-time scheduling policies still use process priorities and queues.
However, current, non-real-time (normal) scheduling policies use the Completely Fair Scheduler (CFS), which instead organizes processes that are awaiting CPU time into a binary search tree.
This process priority uses the SCHED_NORMAL or SCHED_OTHER policies as the default scheduling policy.
Processes that run under the SCHED_NORMAL policy are assigned a static real-time priority of 0, to ensure that all system real-time processes have a higher priority than normal processes.
However, this static priority value is not included when organizing normal process threads for CPU scheduling.
Instead, the CFS scheduling algorithm arranges normal process threads into a time-weighted binary tree, where the first item has the lowest previously spent CPU time, and the last item has the most cumulative CPU time.
The order of the binary tree is additionally influenced by a user-modifiable, per-process nice value, which ranges from -20 (increased priority) to 19 (decreased priority), with a default of 0.
Processes inherit their starting nice value from their parent process.
All users can adjust the nice value to decrease priority, but only root can increase its priority.
A higher nice value indicates a decrease in the process priority from the default, or making the process nicer to other processes. A lower nice value indicates an increase in the process priority from the default, or making the process less nice to other processes.
Increasing the nice value lowers the thread's position, and decreasing the value raises the thread's position.
Important
Generally, priorities determine only indirectly the amount of CPU time that a process thread receives. On a non-saturated system with available CPU capacity, every process is scheduled for immediate CPU time, for as much time as each process wants. Relative process importance, as managed in the binary tree, determines only which threads are selected and placed on CPUs first.
On a CPU-saturated system, where more waiting threads than CPU processing units exist, higher-priority (lower nice) process threads are placed first, until all CPU units are busy, while the lower-priority (higher nice) threads initially must wait in the binary tree. However, the Completely Fair Scheduler is designed to balance process importance, nice values, and previous cumulative CPU time, and dynamically adjusts the binary tree such that all processes obtain fair CPU time.
Privileged users can decrease the nice value of a process, to make a process less nice. A process is then repetitively placed higher in the binary tree, and therefore is scheduled more often. On a saturated system, the overall CPU time available to other processes is reduced.
Unprivileged users can only increase the nice value on their own processes, which makes their own processes nicer, and therefore lowers their placement in the binary tree. Unprivileged users cannot decrease their processes' nice values to raise their importance, nor can they adjust the nice values for another user's process.
Nice values map to a priority value, and both values are available for viewing in process listing commands.
A nice value of -20 maps to a 0 priority in the top command.
A nice value of 19 maps to a 39 priority in the top command.
In the preceding figure, the nice values are aligned with the priority values that are used by the top command.
The top command displays the process priority in the PR column, and the nice value in the NI column.
The top priority numbering scheme, which displays real-time process priorities as negative numbers, is a legacy of internal priority algorithms.
The following output is the summary and a partial process listing in the top command:
Tasks: 192 total, 1 running, 191 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 1.6 sy, 0.0 ni, 96.9 id, 0.0 wa, 0.0 hi, 1.6 si, 0.0 st
MiB Mem : 5668.6 total, 4655.6 free, 470.1 used, 542.9 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 4942.6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 172180 16232 10328 S 0.0 0.3 0:01.49 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 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_gpThe ps command displays process nice values, when using the default formatting options.
The following ps command lists all processes with their process ID, process name, nice value, and scheduling class.
The processes are sorted in descending order by nice value.
In the CLS scheduling class column, TS stands for time sharing, which is another name for the normal scheduling policies, including SCHED_NORMAL.
Other CLS values, such as FF for first in first out and RR for round robin, indicate real-time processes.
Real-time processes are not assigned nice values, as indicated by the dash (-) in the NI column.
Advanced scheduling policies are taught in the Red Hat Performance Tuning: Linux in Physical, Virtual, and Cloud (RH442) course.
[user@host ~]$ ps axo pid,comm,nice,cls --sort=-nice
PID COMMAND NI CLS
33 khugepaged 19 TS
32 ksmd 5 TS
814 rtkit-daemon 1 TS
1 systemd 0 TS
2 kthreadd 0 TS
5 kworker/0:0-cgr 0 TS
7 kworker/0:1-rcu 0 TS
8 kworker/u4:0-ev 0 TS
15 migration/0 - FF
...output omitted...When a process is created, it inherits its parent's nice value. When a process starts from the command line, it inherits its nice value from the shell process. Typically, new processes run with the default nice value of 0.
The following example starts a process from the shell, and displays the process's nice value.
Note the use of the PID option in the ps command to specify the requested output.
Note
This command was chosen for demonstration for its low resource consumption.
[user@host ~]$sleep 60 &[1] 2667 [user@host ~]$ps -o pid,comm,nice 2667PID COMMAND NI 2667 sleep0
All users can use the nice command to start commands with a default or higher nice value.
Setting a higher value by default ensures that the new process is a lower priority than your current working shell, and would less likely affect your current interactive session.
The following example starts the same command as a background job with the default nice value, and displays the process's nice value:
[user@host ~]$nice sleep 60 &[1] 2736 [user@host ~]$ps -o pid,comm,nice 2736PID COMMAND NI 2736 sleep10
Use the nice command -n option to apply a user-defined nice value to the starting process.
The default is to add 10 to the process's current nice value.
The following example starts a background job with a user-defined nice value of 15 and displays the result:
[user@host ~]$nice -n 15 sleep 60 &[1] 2673 [user@host ~]$ps -o pid,comm,nice 2740PID COMMAND NI 2740 sleep15
You can change the nice value of an existing process with the renice command.
This example uses the process ID from the previous example to change from the current nice value of 15 to a new nice value of 19.
[user@host ~]$renice -n 19 27402740 (process ID) old priority 15, new priority19
You can also use the top command to change the nice value on an existing process.
From the top interactive interface, press the r key to access the renice command.
Enter the process ID, and then enter the new nice value.