Processes on a UNIX system are sequentially assigned resources for execution. The kernel assigns the CPU to a process for a time slice; when the time has elapsed, the process is placed in one of several priority queues. How the execution is scheduled depends on the priority assigned to the process. System processes have a higher priority than all user processes.
User process priorities depend on the amount of CPU time they have used. Processes that have used large amounts of CPU time are given lower priorities; those using little CPU time are given high priorities. Scheduling in this way optimizes interactive response times, because processor hogs are given lower priority to ensure that new commands begin execution.
Because process scheduling (and the priorities it is based on) can greatly affect overall system responsiveness, the UNIX system does not allow much user control of time-shared process scheduling. You can, however, influence scheduling with the nice command, which is discussed next.
The nice command allows a user to execute a command with a lower-than-normal priority The process that is using the nice command and the command being run must both belong to the time-sharing scheduling class. The priocntl command, discussed later in this chapter, is a general command for time-shared and real-time priority control.
The priority of a process is a function of its priority index and its nice value. That is,
Priority=Priority Index+nice value.
You can decrease the priority of a command by using nice to reduce the nice value. If you reduce the priority of your command, it uses less CPU time and runs slower. In doing so, you are being “nice” to your neighbors. The reduction in nice value can be specified as an increment to nice. Valid values are from −1 to −19; if no increment is specified, a default value of −10 is assumed. You do this by preceding the normal command with the nice command. For example, the command
$ nice proofit
will run the proofit command with a priority value reduced by the default of 10 units. The command
$ nice −19 proofit
will reduce it by 19. The increment provided to nice is an arbitrary unit, although nice −19 will run slower than nice −9.
Because a child process inherits the nice value of its parent, running a command in the background does not lower its priority. If you wish to run commands in the background, and at a lower priority, place the command sequence in a file (e.g., script) and issue the following commands:
$ nice −10 script &
The priority of a command can be increased by the superuser. A higher nice value is assigned by using a double minus sign (or a + sign for some UNIX variants, such as Solaris and AIX). For example, you increase the priority by 19 units with the following command:
# nice −−19 draftit
Another simple way to affect scheduling is with the sleep command. The sleep command does nothing for a specified time. You can have a shell script suspend operation for a period by using sleep. The command
sleep time
included in a script will delay for time seconds. You can use sleep to control when a command is run, and to repeat a command at regular intervals. For example, the command
$ (sleep 3600; who >> log) &
provides a record of the number of users on a system in an hour. It creates a process in the background that sleeps (suspends operation) for 3,600 seconds; and then wakes up, runs the who command, and places its output in a file named log.
You can also use sleep within a shell program to regularly execute a command. The script
$ (while true > do > sleep 600 > finger barbara >done)&
can be used to watch whether the user barbara is logged on every ten minutes. Such a script can be used to display in one window (in a window environment such as X) while you remain active in another window.
When a shell uses the system call fork to create a child process, it suspends operation and waits until the child process terminates. When a job is run in the background, the shell continues to operate while other jobs are being run.
Occasionally, it is important in shell scripts to be able to run simultaneous processes and wait for their conclusion before proceeding with other commands. The wait command allows this degree of scheduling control within shell scripts, and you can have some commands running synchronously and others running asynchronously. For example, the sequence
command1 > file1 & command2 > file2 & wait sort file1 file2
runs the two commands simultaneously in the background. It waits until both background processes terminate, and then it sorts the two output files.
When you use the ps command (process status) with options, you can control the information displayed about running processes. Note that some of the information as well as the order in which it is displayed may differ slightly between variants, but it provides enough information to uniquely identify a process and its status. The -f option provides a full listing of your processes. In the example that follows, the first column identifies the login name (UID) of the user, the second column (PID) is the process ID, and the third (PPID) is the parent process ID-the ID number of the process that spawned this one. The C column represents an index of recent processor utilization, which is used by the kernel for scheduling. STIME is the starting time of the process in hours, minutes, and seconds; a process more than 24 hours old is given in months and days. TTY is the terminal ID number. TIME is the cumulative CPU time consumed by the process, and COMD is the name of the command being executed:
$ ps -f UID PID PPID C STIME TTY TIME COMD dah 17118 3211 0 15:57:07 term/41 0:01 /usr/bin/vi perf.rev dah 3211 1 0 15:16:16 term/41 0:00 /usr/lbin/ksh dah 2187 17118 0 16:35:41 term/41 0:00 sh -I dah 4764 2187 27 16:43:56 term/41 0:00 ps -f
Notice that with the -f option, ps does not simply list the command name. ps -f uses information in a process table maintained by the kernel to display the command and its options and arguments. In this example, you can see that user dah is using vi to edit a file named perf.rev, has invoked ps with the -f option, and is running an interactive version of the Bourne shell, sh, as well as the Korn shell, ksh. The ksh is this user’s login shell, since its parent process ID (PPID) is 1.
The fact that ps -f displays the entire command line is a potential privacy and security problem. You can check the processes used by another user with the -u user option. ps -u nick will show you the processes being executed by nick, and ps -f -u nick will show them in their full form. The user anni may not want you to know that she’s editing her résumé, but the information is there in the ps output:
$ ps -f -u anni UID PID PPID C STIME TTY TIME COMD anni 8896 1 0 09:47:23 term/11 0:00 ksh anni 12958 18896 0 17:10:25 term/11 0:00 vi resume
If you don’t wish others to see the name of the file you are editing, don’t put the name on the command line. With ed, vi, and emacs you can start the editor without specifying a filename on the command line, and then read a file into the editor buffer (see Chapter 5 for more info).
Of course, you should never specify the key on the command line when you use crypt (described in Chapter 12). If you don’t supply a key, crypt will prompt you for one. If you use crypt -k, the shell variable CRYPTKEY will be used as a key In either case, the key will not appear in a ps -f listing.
The -l option provides a long form of the ps listing. The long listing repeats some of the information just discussed as well as some additional fields. While the display format differs slightly between the variants (Linux output format is slightly different than the Solaris/HP-UX format), the content is basically the same. In the following example, the first column, F, specifies a set of additive hex flags that identify characteristics of the process; for example, process has terminated, 00; process is a system process, 01; process is in primary memory 08; process is locked, 10. The second column identifies the current state of the process.
>Process State (S) Abbreviation | Meaning |
---|---|
0 | Process running |
S | Process sleeping |
R | Runnable process in queue |
I | Idle process, being created |
Z | Zombie |
T | Process stopped and being traced |
X | Process waiting for more memory |
For example,
$ ps −1 F s UID PID PPID C PRI NI ADDR sz WCHAN TTY TIME COMD 100 s 4392 17118 3211 0 30 20 1C40368 149 10d924 term/41 0:01 vi 0 O 4392 4847 2187 37 3 20 32686d0 37 term/41 0:00 ps 100 s 4392 3211 1 0 30 20 2129000 52 1161a4 term/41 0:00 ksh 100 s 4392 2187 17118 8 30 20 35a7000 47 1176a4 term/41 0:00 ksh
The PRI column contains the priority value of the process (a higher value means a lower priority) and NI is the nice value for the process. (See the section “The nice Command” earlier in this chapter.) ADDR represents the starting address in memory of the process. SZ is the size, in pages, of the process in memory.
If you use the -e option, you will display every process that is running on your system. This is not very interesting if you are just a user on a UNIX system. Dozens of processes may be active even if there are only a few people logged in. It can be important if you are administering your own system. For instance, you may find that a process is consuming an unexpectedly large amount of CPU time or has been running longer than you would like. A few lines of the output of ps with the -e option might look something like this:
$ ps -e PID TTY TIME COMMAND 0 ? 0:34 sched 1 ? 41:55 init 23724 console 0:03 sh 272 ? 2:47 cron 7015 term/12 20:24 vi 497 term/52 0:01 uugetty 499 ? 0:01 getty 5424 ? 0:00 cat
Like the ps command with no arguments, ps -e displays the process ID, the terminal (with a ? shown if the process is attached to no terminal), the time, and the command name. In this example, terminal 12 has a vi program associated with it that is using a lot of CPU time. This is unusual, since vi normally is not used in especially long sessions, nor does it normally use much CPU time.
This is sufficiently abnormal to warrant checking. For example, an interloper may be running a program that consumes a lot of resources, which he has named vi to make it appear a normal, innocent command.
As a system administrator, you can use the ps -e command to develop a sense of what your system is doing at various times.