For workstations, resource allocation is usually not an issue because only a small number of applications are generally running at any one time. Of these applications, CDE and X11 may consume the largest amount of CPU time, particularly if the workspace is fully utilized. However, servers have very diverse needs with respect to resource management, particularly in a shared hosting environment, where time and process priority are billable items. Being able to specify which processes have priority over others is a key requirement for servers running hundreds of different processes for potentially hundreds of different customers.
EXAM TIP |
You should be able to identify the different priority classes and values utilized by the kernel. |
The concept of process priority is built in to the kernel: if processes belong to the time sharing (TS) priority class, a priority value (PRI) may be assigned to them that determines the order in which their operations are executed on the CPU. The scheduler is responsible for allocating resources to different processes according to priority values.
Tip |
Nonprivileged users can only decrease the priority associated with their processes, while the superuser can actually increase the priority associated with any user’s processes. |
One way to appreciate this is to use the ps command to display the process list in the scheduler format. This includes two extra columns in the ps output: the priority class memberships, and the process priority values:
$ ps -c PID CLS PRI TTY TIME CMD 6667 TS 45 pts/8 0:00 sh 6675 TS 35 pts/8 0:00 httpd
In this example, the httpd command and the Bourne shell (sh) are both members of the Time Sharing class, meaning that a priority value may be assigned to their respective processes. In this example, the sh process has a higher priority value than the httpd process, and thus has greater access to the system’s resources.
An unprivileged user can reduce any of the processes they own by reducing the priority granted to the ps process—this is done by using the nice command for a new process, or the renice command for an existing process. The following example reduces the priority for sh by increasing the nice value, potentially increasing the amount of CPU available for the httpd process:
$ renice -30 sh
This would reduce the priority for the sh process to 15, well below the priority for httpd at 35. Alternatively, the superuser may directly increase the priority of a process by specifying a negative increment, which when subtracted from the process priority actually increases it (that is, subtracting a negative integer is equivalent to addition). The following example would increase the process priority for the httpd command from 35 to 55:
# renice --20 ps
Keep in mind that the C shell has a built-in nice function that differs from the /usr/bin/nice command. The nice command only solves part of the problem of resource allocation, because normal users still have unbounded access to execute as many applications as they wish unless the superuser continually monitors their activity, reducing priority values when necessary. In a multiprocessor system, it may be possible to run an "honor system," where individuals or groups agree only to use a specific CPU for their work by using the pbind command. pbind forces a process and its children to only use a specific CPU. For example, if an httpd process was started, and it had a PID of 2234, it could be bound to CPU 1 by using the following command:
$ pbind -b 1 2234 process id 2234: was 1, now 1
Again, a superuser can bind (or unbind) any process from a specific CPU if resources are being drained by using the pbind command. But this still requires monitoring and oversight from a system administrator. Another alternative is to create a processor set by using the psrset command, which binds a process to a single CPU or to a group of CPUs. This limits the maximum CPU usage by a specific process to whatever it can obtain from the CPU (or CPUs) it is bound to. The problem here is that a system has limited resources, so if a process does not use all of the CPU allocated to it, resources are being wasted as the CPU sits idling.
What is really required is a policy-based mechanism for ensuring that individual users and applications never exceed a preallocated quota of CPU resource, much like how disk quotas specify exactly how much disk space a user can utilize. The Resource Manager provides this functionality by implementing a fine-grained resource access policy, which limits the resources that can be utilized by different users. It allows CPU usage to be allocated on a per-user basis, and virtual memory consumption to be limited on both a user and process basis. In addition, the total number of processes spawned by a user, the number of concurrent logins, and their total connection time can be limited. This allows complete control over an individual user’s access to the system, as well as to their individual processes. For example, a numerical scientist might have free access to the system except when running the Matlab (www.mathworks.com) application, where the matlab process might be limited to how much CPU and virtual memory can be consumed.
The simplest method of allocating CPU resources is to divide up the available CPU resources among the existing users according to organizational priorities. For example, a web server for an online catalogue may have three main accounts whose access to resources needs to be limited: the oracle account, responsible for running the Oracle database; the apache user, responsible for running the Apache web server; and the jdk user, responsible for executing the Java Virtual Machine (JVM) for the Apache Tomcat servlet runner. In order to prevent large numbers of httpd clients from causing a resource drain on the database, or from thread lock in the JVM causing the same problem, it is necessary to limit the maximum CPU usage of the httpd and java processes by setting limits on the amount of CPU that the apache and jdk users can utilize.
Since the Resource Manager allows for the hierarchical allocation of resources to groups of users and processes (known as sgroups), all allocations must descend from the root sgroup. In our example, only the root sgroup will be used, so we first associate the oracle, apache, and jdk users as descendants of the root sgroup by using the limadm command:
# limadm set sgroup=root oracle # limadm set sgroup=root apache # limadm set sgroup=root jdk
If the allocation of CPU to the oracle, apache, and jdk was 50 percent, 25 percent, and 25 percent, respectively, the following commands would set the share of each user appropriately:
# limadm set cpu.shares=50 oracle # limadm set cpu.shares=25 apache # limadm set cpu.shares=25 jdk
To check the status of the resources being used by the oracle user, we could use the liminfo command:
# liminfo -c oracle Login name: oracle Uid (Real,Eff): 1024 (-,-) Sgroup (uid) root(0) Gid (Real,Eff): 10(-,-) Shares: 50 Myshares: 1 Share: 50 % E-share: 0 % Usage: 0 Accrued usage: 0 Mem usage: 0 B Term usage: 0s Mem limit: 0 B Term accrue: 0s Proc mem limit: 0 B Term limit: 0s Mem accrue: 0 B.s Processes: 2 Current logins: 1 Process limit: 0
More complex sgroups can be created for a system, based on organizational units. For example, the sales division may require 25 percent of the CPU in a system while the finance division may be entitled to 75 percent. Individual sgroups must be created for each of these divisions underneath root, and then individual users who are members of the divisions must be associated with the correct sgroup.