Processes and Scheduling - System Administration - UNIX: The Complete Reference (2007)

UNIX: The Complete Reference (2007)

Part III: System Administration

Chapter List

Chapter 11: Processes and Scheduling

Chapter 12: System Security

Chapter 13: Basic System Administration

Chapter 14: Advanced System Administration

Chapter 11: Processes and Scheduling


The notion of a process is one of the most important aspects of the UNIX system, along with files and directories and the shell. All UNIX variants use this notion in the same way. A process, or task, is an instance of an executing program. It is important to make the distinction between a command and a process; you generate a process when you execute a command. UNIX is a multitasking system because it can run many processes at the same time. At any given time there may be tens or even hundreds or thousands of processes running on your system.

This chapter will show you how to monitor the processes you are running by using the ps command and how to terminate running processes by using the kill command, for instance, to kill runaway processes that are taking inordinate amounts of time. You will also see how to use the ps command with options to monitor all the processes running on a system.

In this chapter, you will learn how to schedule the execution of commands. You will see how to use the at command to schedule the execution of commands at particular times and how to use the batchcommand to defer the execution of a command until the system load permits.

You will also be introduced to a special type of process called the daemon. This process can invoke other processes. Some daemon processes are loaded automatically at system startup or when a certain event occurs, while others may be started manually by your system administrator.

Support for real-time processing is an important feature of UNIX that makes it possible to run many applications requiring predictable execution. This chapter describes many of the capabilities of UNIX that support real-time processing. You will see how to set the priorities of processes, including giving processes real-time priority

You will also learn about the /proc file system, a virtual file system that provides a wealth of information to both system administrators and users.


The term process was first used by the designers of the Multics operating system, an ancestor of the UNIX operating system. Process has been given many definitions. In this chapter, we use the intuitive definition that makes process equivalent to task, as in multiprocessing or multitasking. In a simple sense, a process is a program in execution. However, because a program can create new processes (e.g., the shell spawns new shells), for a given program, there may be one or more processes in execution.

At the lowest level, a process is created by a fork system call. (A system call is a routine that causes the kernel to provide some service for a program.) A fork creates a separate, but almost identical running process. The process that makes the fork system call is called the parent process; the process that is created by the fork is called the child process. The two processes have the same environment, the same signal-handling settings, the same group and user IDs, and the same scheduler class and priority but different process ID numbers. The only way to increase the number of processes running on a UNIX system is with the fork system call. When you run programs that spawn new processes, they do so by using the fork system call.

The way you think about working on a UNIX system is tied to the concepts of the file system and of processes. When you deal with files in UNIX, you have a strong “locational” feeling. When you are in certain places in the file system, you use pwd (present working directory) to see where you are, and you move around the file system when you execute a cd (change directory) command.

A special metaphor applies to processes in UNIX. The processes have life: they are alive or dead; they are spawned (born) or die; they become zombies or they become orphaned. They are parents or children,and when you want to get rid of one, you kill it.

On early PCs, only one program at a time could be run, and the user had exclusive use of the machine. On a time-sharing system like UNIX, users have the illusion of exclusive use of the machine even though dozens or hundreds of others may be using it simultaneously The UNIX kernel manages all the processes executing on the machine by controlling the creation, operation, communication, and termination of processes. It handles sharing of computer resources by scheduling the fractions of a second when the CPU is executing a process, and by suspending and rescheduling a process when its CPU time allotment is completed.

There are two categories of processes running on a UNIX system, foreground and background. A foreground process is one that is run by executing a command at the command line, such as the ps command in the following section. When running a foreground process, the command is executed immediately The system will devote whatever resources are necessary to complete the process, and-when the process is completed-the shell prompt will appear, indicating that the process is complete. A background process is one where the process is scheduled for execution at a later time when resources are available, according to priorities set by the system administrator.

The ps Command

To see what is happening on your UNIX system, use the ps (process status) command. The ps command lists all of the active processes running on the machine. If you use ps without any options, information is printed about the processes associated with your terminal. For example, the output from ps shows the process ID (PID), the terminal ID (TTY), the amount of CPU time in minutes and seconds that the command has consumed, and the name of the command, as shown here:

$ ps


3211 term/41 0:05 ksh

12326 term/41 0:01 ps

12233 term/41 0:20 ksh

9046 term/41 0:02 vi

This user has four processes attached to terminal ID term/41; there are two Korn shells (ksh), a vi editing session, and the ps command itself.

Process ID numbers are assigned sequentially as processes are created. Process 0 is a system process that is created when a UNIX system is first turned on, and process 1 is the init process from which all others are spawned. Other process IDs start at 2 and proceed with each new process labeled with the next available number. When the maximum process ID number is reached, numbering begins again, with any process ID number still in use being skipped. The maximum ID number can vary, but it is usually set to 32767.

Because process ID numbers are assigned in this way, they are often used to create relatively unique names for temporary user files. The shell variable $$ contains the process ID number of that shell, and $$ refers to the value of that variable. If you create a file temp$$, the shell appends the process ID to temp. Because every current process has a unique ID, your shell is the only one currently running that could create this filename. A different shell running the same script would have a different PID and would create a different filename. For example,

#touch temp$$

would create a temp file with the currently running process ID appended. If the current PID happened to be 3464, the created file would be named temp3464.

When you start up or boot a UNIX system, the UNIX kernel (/unix) is loaded into memory and executed. The kernel initializes its hardware interfaces and its internal data structures and creates a system process, process 0, known as the swapper. Process 0 forks and creates the first user-level process, process 1.

Process 1 is known as the init process because it is responsible for setting up, or initializing, all subsequent processes on the system. It is responsible for setting up the system in single-user or multiuser mode, for managing communication lines, and for spawning login shells for the users. Process 1 exists for as long as the system is running, and it is the ancestor of all other processes on the system.

How to Kill a Process

You may want to stop a process while it is running. For instance, you may be running a program that contains an endless loop, so that the process you created will never stop. Or you may decide not to complete a process you started, either because it is hogging system resources or because it is doing something unintended. If your process is actively running, just hit the BREAK or DELETE key However, you cannot terminate a background process or one attached to a different terminal this way, unless you bring it back to the foreground.

You should observe some cautions when using kill to end processes. Before you attempt to kill a process, you should ensure that you have correctly identified the process ID (PID) you wish to kill. In this “family” relationship that is built as processes spawn others, you can inadvertently kill a process that is the parent of the one you want to kill, and leave an orphan, or-in the worst case-a zombie (a process that still appears in the process table as though it were active, but either has been killed or has completed and is consuming no resources).

You may also transpose numbers in the PID and kill a process that is being used for a different purpose, even a system-level process. The results can be disastrous, especially if you use what is known as a “sure (or unconditional) kill.” This type of kill is discussed in the next section.

To terminate such a process, or kill it, use the kill command, giving the process ID as an argument. For instance, to kill the process with PID 2312 (as revealed by ps), type

$ kill 2312

This command sends a signal to the process. In particular, when used with no arguments, the kill command sends the signal 15 to the process. (Over 30 different signals can be sent on UNIX systems. See Table 11–1, in the section “Signals and Semaphores,” for a list.) Signal 15 is the software termination signal (SIGTERM) that is used to stop processes.

Table 11–1: The Thirty Most Common UNIX Signals















Illegal instruction



Trace/breakpoint trap






Emulation trap



Floating point exception






Bus error



Segmentation fault



Bad system call



Broken pipe



Alarm clock






User signal 1



User signal 2



Child status changed



Power failure



Window size change



Urgent socket condition



Pollable event






Stopped (user)






Stopped terminal input



Stopped terminal output



Virtual timer expired



Profiling timer expired



CPU time exceeded

Some processes, such as the shell, do not die when they receive this signal. You can kill processes that ignore signal 15 by supplying the kill command with the −9 flag. This sends the signal 9, which is the unconditional kill signal, to the process. For instance, to kill a shell process with PID 517, type

$ kill −9 517

You may want to use kill −9 to terminate sessions. For instance, you may have forgotten to log off at work. When you log in remotely from home and use the ps command, you will see that you are logged in from two terminals. You can kill the session you have at work by using the kill −9 command.

To do this, first issue the ps command to see your running processes:

$ ps


3211 term/41 0:05 ksh

12326 term/41 0:01 ps

12233 term/15 0:20 ksh

You can see that there are two kshs running: one attached to terminal 41, one, to terminal 15. The ps command just issued is also associated with terminal 41. Thus, the ksh associated with term/15, with process number (PID) 12233, is the login at work. To kill that login shell, use the command

$ kill −9 12233

You can also kill all the processes that you created during your current terminal login session. A process group is a set of related processes, for example, all those with a common ancestor that is a login shell. Use the command

$ kill 0

to terminate all processes in the process group.

If you program in Shell (see Chapter 20), you may want to know if a particular process is running prior to executing a command. The −0 (zero) option of kill allows you to do this. Putting the string

kill −0 pid

into your shell script will return a value indicating whether or not the indicated process (pid) is alive.

Parent and Child Processes

When you type a command line on your UNIX system, the shell handles its execution. If the command is a built-in command known by the shell (echo, break, exit, test, and so forth), it is executed internally without creating a new process. If the command is not a built-in, the shell treats it as an executable file. The current shell uses the system call fork and creates a child process, which executes the command. The parent process, the shell, waits until the child either completes execution or dies, and then it returns to read the next command.

Normally when the shell creates the child process, it executes a wait system call. This suspends operation of the parent shell until it receives a signal from the kernel indicating the death of a child. At that point, the parent process wakes up and looks for a new command.

When you issue a command that takes a long time to run (e.g., a troff command to format a long article), you usually need to wait until the command terminates. When the troff job finishes, a signal is sent to the parent shell, and the shell begins paying attention to your input once again. You can run multiple processes at the same time by putting jobs into the background. If you end a command line with the ampersand (&) symbol, you tell the shell to run this command in the background. The command string

$ cat * troff -mm lp 2> /dev/null &

causes all the files in the current directory to be formatted and sent to the printer. Because this command would take several minutes to run, it is placed in the background with the & symbol.

When the shell sees the & at the end of the command, it forks off a child shell to execute the command, but it does not execute the wait system call. Instead of suspending operation until the child dies, the parent shell resumes processing commands immediately If anything goes wrong with the process, the output of the lp command is redirected to the device /dev/ null (discarded) to avoid a lengthy printout of garbage.

The shell provides programming control of the commands and shell scripts you execute. The command format

$ (command; command; command) &

instructs the shell to create a child or subshell to run the sequence of commands, and to place this subshell in the background.

Process Scheduling

As a time-sharing system, the UNIX system kernel directly controls how processes are scheduled. User-level commands are available that allow you to specify when you would like processes to be run.

The at Command

You can specify when commands should be executed by using the at command, which reads commands from its standard input and schedules them for execution. Normally, standard output and standard error (see Chapter 4) are mailed to you, unless you redirect them elsewhere. UNIX accepts several ways of indicating the time; consult the manual page at(1) for all the alternatives. Here are some examples of alternative time and date formats:

at 0500 Jan 18

at 5:00 Jan 18

at noon

at 5 pm tomorrow

The at command is handy for sending yourself reminders of important scheduled events. For example, the command

$ at 6 am Friday

echo "Don't Forget The Meeting with BOB at 1 PM!!" mail you


will mail you the reminder early Friday morning. at continues to read from standard input until you terminate input with CTRL-D.

You can redirect standard output back to your terminal and use at to interrupt with a reminder. Use the ps command just discussed to find out your terminal number. Include this terminal number in a command line such as this:

$ at 1 pm today

echo "^G^GConference call with BOB at 1 PM^G^G" > /dev/term/43


This will display the following message on your screen at 1:00 P.M.

Conference call with BOB at 1 PM

The ^G (CTRL-G) characters in the echo command will ring the bell on the display terminal. Because at would normally mail you the output of banner and echo, you have to redirect them to your terminal if you want them to appear on the screen.

The -f option to at allows you to run a sequence of commands contained in a file. The command

$ at -f scriptfile 6 am Monday

will run scriptfile at 6 A.M. on Monday If you include a line similar to

at -f scriptfile 6 am tomorrow

at the end of scriptfile, the script will be run every morning. You can learn how to write shell daemons in Chapter 20.

If you want to see a listing of all the at jobs you have scheduled, use the command

$ at -1

629377200.a Sun Aug 06 06:00:00 2006

With the -l option, at returns the ID number and scheduled time for each of your at jobs. To remove a job from the queue, use the -r option. The command

at -r 629377200.a

will delete the job scheduled to run at 6 A.M. on August 6, 2006. Notice that the time and date are the only meaningful information provided. To make use of this listing, you need to remember which commands you have scheduled at which times.

The at command is used most effectively when you want to schedule a process that either is not part of a normal routine or is an event you wish to perform only once. While you can use the at command to schedule processes that run routinely, you should use the cron facility (discussed later in this chapter) to do this. The cron command provides more robust management of the process that is requested to be run, and-once set up properly-will run without intervention time after time.

The cron Facility

The cron facility is a system daemon that executes commands at specific times. It is similar in some respects to the at command (previously discussed in this chapter) but is much more useful for repetitive execution of a process. The command and schedule information are kept in the directory /var/spool/cron/crontabs or in /usr/spool/cron/crontabs. Each user who is entitled to directly schedule commands with cron has a crontab file. cron wakes up periodically (usually once each minute) and executes any jobs that are scheduled for that minute.

Entries in a crontab file have six fields, as shown in the following example.

The first field is the minute that the command is to run; the second field is the hour; the third, the day of the month; the fourth, the month of the year; the fifth, the day of the week; and the sixth is the command string to be executed. Asterisks act as wildcards. In the crontab example, the program with the pathname /home/gather is executed and mailed to “maryf” every day at 6 P.M. The program /home/jar/bin/backup is executed every day at 2:30 A.M.





#(0–59) (0–23) (1–31) (1–12) (0–6) (Note: 0=Sun)

#______ ______ ______ ______ _____ _____________


0 18 * * * /home/gather | mail maryf

30 2 * * * /home/jar/bin/backup

The file /etc/cron.d/cron.allow contains the list of all users who are allowed to make entries in the crontab. If you are a system administrator, or if this is your own system, you will be able to modify the crontabfiles. If you are not allowed to modify a crontab file, use the at command to schedule your jobs (unless you are denied access to at jobs via the at.deny file).

The crontab Command

To make an addition in your crontab file, you use the crontab command. For example, you can schedule the removal of old files in your wastebasket with an entry like this:

0 1 * * 0 cd /home/jar/.wastebasket; find . -atime +7 -exec /bin/rm -r {} 2>

/dev/null ;

This entry says, “Each Sunday at 1 A.M., go to jar’s wastebasket directory and delete all files that are more than 7 days old.” If you place this line in a file named wasterm, and issue the command

$ crontab wasterm

the line will be placed in your crontab file. If you use crontab without specifying a file, the standard input will be placed in the crontab file. The command

$ crontab


deletes the contents of your crontab-that is, it replaces the contents with nothing. This is a common error and causes the contents of crontab to be deleted by mistake.

Note that the scheduling of processing depends on the accuracy of the system time. If unpredictable things start happening, you might want to check that this time is accurate.

The batch Command

The batch command lets you defer the execution of a command but does not give you control over when it is run. The batch command is especially handy when you have a command or set of commands to run but don’t care exactly when they are executed. batch will queue the commands to be executed when the load on the system permits. Standard output and standard error are mailed to you unless they are redirected. The here document construct supported by the shell (discussed in Chapter 20) can also be used to provide input to batch.

$ batch <<!

cat mybook tbl | eqn troff -mm lp



Daemons are processes that are not connected to a display; they may run in the background, and they do useful work. Several daemons are normally found on UNIX Systems: user daemons, like the one described in Chapter 20, that clean up your files; and system daemons that handle scheduling and administration. There are also a number of system daemons that are started automatically when the system boots up to set up your network environment and all of the services available to you.

For example, /init.d/ is a standard directory that is used to contain daemon scripts that control user states, mail environments, and even file system choices. Similar daemons handle printing and the operation of the printer spool, file backup, cleanup of temporary directories, and billing operations. Each of these daemons is controlled by cron, which is itself run by init (PID 1).

You can create daemons from processes so that they will start automatically. One way is to consider all the tasks that are affected, the options required, and the security level needed, and then create the daemon process. A simpler way is to use daemon, which is supported on all of the major UNIX/LINUX platforms. daemon can be obtained at It is freeware available under the GNU General Public License.

Process Priorities

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

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

The sleep Command

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


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.

The wait Command

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 &


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.

ps Command Options

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


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 kshis 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


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 Long Form of ps

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



Process running


Process sleeping


Runnable process in queue


Idle process, being created




Process stopped and being traced


Process waiting for more memory

For example,

$ ps −1


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.) ADDRrepresents the starting address in memory of the process. SZ is the size, in pages, of the process in memory.

Displaying Every Process Running on Your System

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


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.

Signals and Semaphores

A signal is a notification sent to a process that an event has occurred. These events may include hardware or software faults, terminal activity, timer expiration, changes in the status of a child process, changes in a window size, and so forth. A list of the 30 most common signals is given in Table 11–1 (there are actually about 45 signals).

Each process may specify an action to be taken in response to any signal other than the kill signal. The action can be any of these:

§ Take the default action for the signal:

o Exit means receiving process is terminated.

o Core means receiving process is terminated and leaves a “core image” in the current directory Using the core dump for debugging is discussed in Chapter 24.

o Stop means receiving process stops.

§ Ignore the signal.

§ On receiving a signal, execute a signal-handling function defined for this process.

Many of the signals are used to notify processes of special events that may not be of interest to a user. Although most of them can have user impact (e.g., power failures and hardware errors), there is not much a user can do in response. A notable exception for users and for shell programmers is the HUP or hangup signal. You can control what will happen after you hang up or log off.

The UNIX systems use signals to notify a specific process about its current state. However, many processes run simultaneously on a typical machine. At times, more than one process may want to use a particular system resource in order to execute. UNIX handles this situation by using semaphores. A semaphore is a value that the operating system makes available to processes to check whether or not the resource is currently being used. If a resource is free (not in use), a process can grab the resource and indicate that the resource is in use by setting the semaphore value to busy If a process requests a resource that is already in use, the semaphore value indicates so, and the process must wait until the resource is freed up. The process periodically checks the status of the desired resource. Once a process is able to access the resource, the process sets the resource’s semaphore to indicate that the resource is busy with this process, and that the next process must wait until the resource is free again. Semaphores are usually binary (0 or 1 state) but can have additional values depending on the resource.

The nohup Command

When your terminal is disconnected, the kernel sends the signal SIGHUP (signal 01) to all processes that were attached to your terminal, as long as your shell does not have job control. The purpose of this signal is to have all other processes terminate. Times frequently arise, however, when you want to have a command continue execution after you hang up. For example, you will want to continue a troff process that is formatting a memorandum without having to stay logged in.

To ensure that a process stays alive after you log off, use the nohup command as follows:

$ nohup command

The nohup command is a built-in shell command in sh, ksh, and csh. In some earlier versions of UNIX the nohup command was a shell script that trapped and ignored the hangup signal. It basically acted like this:

$ (trap '' 1; command) &

nohup refers only to the command that immediately follows it. If you issue a command such as

$ nohup cat file | sort lp

or if you issue a command such as

$ nohup date; who ; ps -ef

only the first command will ignore the hangup signal; the remaining commands on the line will die when you hang up. To use nohup with multiple commands, either precede each command with nohup or, preferably, place all commands in a file and use nohup to protect the shell that is executing the commands:

$ cat file



ps -ef

$ nohup sh file

Zombie Processes

Normally, UNIX system processes terminate by using the exit system call. The call exit (status) returns the value of status to the parent process. When a process issues the exit call, the kernel disables all signal handling associated with the process, closes all files, releases all resources, frees any memory, assigns any children of the exiting process to be adopted by init, sends the death of a child signal to the parent process, and converts the process into the zombie state. A process in the zombie state is not alive; it does not use any resources or accomplish any work. But it is not allowed to die until the exit is acknowledged by the parent process.

If the parent does not acknowledge the death of the child (because the parent is ignoring the signal, or because the parent itself is hung), the child stays around as a zombie process. These zombie processes appear in the ps -f listing with <defunct> in place of the command:


root 21671 21577 0 0:00 <defunct>

root 21651 21577 0 0:00 <defunct>

Because a zombie process consumes no CPU time and is attached to no terminal, the STIME and TTY fields are blank. In earlier versions of the UNIX System, the number of these zombie processes could increase and clutter up the process table. In more recent versions of the UNIX System, the kernel automatically releases the zombie processes.

Real-Time Processes

Many types of applications require deterministic and predictable execution. These include factory automation programs; programs that run telephone switches; and programs that monitor medical information, such as heartbeats. Current workstations can play digitally stored music or voice recordings as well as movies. Acceptable playback of these materials requires that pauses not be introduced by the system. Early releases of UNIX ran all processes on a time-sharing basis, allocating resources according to an algorithm that allowed different processes to take turns using system resources. This made it impossible to guarantee that any process would run at a specific time within a specific time interval.

UNIX systems today have support for real-time processes. The real-time enhancements can be used to support many kinds of applications requiring deterministic and predictable processing, such as running processes on dedicated processors used for monitoring devices. However, some real-time applications, such as robotics, that depend on deterministic processing with extremely short scheduling intervals are still difficult to implement because of limitations involving how the UNIX system kernel and input/output work. Some of these limitations will be eliminated in future releases of UNIX.

Priority Classes of Processes

UNIX supports five configurable classes of processes with respect to scheduling: the real-time class (RT), the fixed-priority class (FX), the time-sharing class (TS), the fair-share class (FS), and the interactive class (IA). Each class has its own scheduling policy, but a real-time process has priority over every time-sharing or interactive process. The interactive class is basically the same as the time-sharing class, with an additional priority given to it as an active window task.

Besides these classes, there is a sixth class, the system class (SYS), which consists of special system processes needed for the operation of the system. The system class is reserved for use by the kernel. You cannot change the scheduling parameters for these processes. Also, you cannot change the class of any other process to the system class. Processes in the system class have priority over all other processes.

Real-Time Priority Values

A process in the real-time class has a real-time priority value (rtpi value) between 0 and x. The parameter x, the largest allowable value, can be set for a system. The process with the highest priority is the real-time process with the highest rtpi value. This process will run before every other process on the system (except system class processes).

Time-Sharing User Priority Values

Each process in the time-sharing class has a time-sharing user priority (tsupri) value between −x and x, where the parameter x can be set for your system. Increasing the tsupri value of a process raises its scheduling priority However, unlike a real-time process, a time-sharing process is not guaranteed to run prior to time-sharing processes with lower tsupri values, because the tsupri value is only one factor used by the UNIX System to schedule the execution of processes.

Setting the Priority of a Process

To use the priocntl command to change the scheduling parameters of a process to real-time, you must be the superuser or you must be running a shell that has real-time priority Also, to change the scheduling parameters of a process to any class, your real or effective ID must match the real or effective ID of that process, or you must be the superuser.

Assuming you meet these requirements, you can set the scheduling class and priority of a process by using the priocntl command with the -s (Set) option. For example,

# priocntl -s -c RT -p 2 -i pid 117

sets the class of the process with process ID 117 as real-time and assigns it a real-time priority value of 2. The command

# priocntl -s -c RT -i ppid 2322

sets the class of all processes with parent process ID 2322 as real-time and assigns these processes the real-time priority value of 0, since the default value of rtpi for a real-time process is 0.

The general form of the priocntl command with the -s option is

# priocntl -s [-c class] [class-specific options] [-i idtype] [idlist]

The minimum requirement for changing the scheduling parameters of a process is that your real or effective ID must match the real or effective ID of that process, or you must be the superuser.

Executing a Process with a Priority Class

You can use the priocntl command with the -e (execute) option to execute a command with a specified class and priority. For instance, to run a shell, using the sh command, as a real-time process with the real-time priority value of 2, use the command line

# priocntl -e -c RT -p 2 sh

(A system administrator may want to run a shell with a real-time priority if the system is heavily loaded and some administrative tasks need to be carried out rapidly)

The general form of the priocntl command with the -e option is

# priocntl -e [-c class] [class-specific options] [-i idtype] [idlist]

Time Quanta for Real-Time Processes

The priocntl command can also be used to control the time quantum, tqntm, allotted to a real-time process. The time quantum specifies the maximum time that the CPU will be allocated to a process, assuming the process does not enter a wait state. Processes may be preempted before receiving their full time quantum if another process is assigned a higher real-time priority value.

You can set the time quantum for a process by using the -t (tqntm) option to prioctnl. The default resolution for time quanta is in milliseconds. For instance,

# priocntl -s -c RT -p 20 -t 100 -i pid 1821

sets the class of the process with PID 1821 to be real-time, with rtpi 30 and a time quantum of 100 milliseconds, which is 1/10 of a second.

You can also assign a time quantum when you execute a command. For instance,

# priocntl -e -c RT -p 2 -t 100 sh

executes a shell with a real-time priority value of 2 and a time quantum of 100 milliseconds.

Displaying the Priority Classes of Processes

You can use the priocntl command with the -d (display) option to display the scheduling parameters of a set of processes. You can specify the set of processes for which you want scheduling parameters. For instance, you can display the scheduling parameters of all existing processes using the command line shown here:

# priocntl -d -i all



1 0 0

306 0 0

115 0 0

15291 1 1

1677 8 4

157 0 0

15306 0 0

1725 0 −8

15307 0 0

1668 0 0

1698 10 10

15305 0 0

6154 −4 −4

15310 0 0



1888 15 1000

15317 2 100

15313 2 100

15315 2 100

1003 0 1000

918 50 1000 +

On Solaris 10 UNIX, you can use the ps command to do this:

# ps -ecl

will display a list of all the running processes, including the class they are running under (shown as SYS), as well as the priority of the process (shown as PRI).

You can also display scheduling parameters for only one class of processes. For instance, you can use the command line

# priocntl -d -i class TS

to display scheduling parameters for all existing time-sharing processes.

You can further restrict the processes for which you display scheduling parameters by using the -i option. For instance, the command

# priocntl -d -i pid 912 3032 3037

displays scheduling parameters of the processes with process IDs 912, 3032, and 3037. The command

# priocntl -d -i ppid 2239

displays the scheduling parameters of all processes whose parent process ID is 2239.

The general form of the priocntl command that you use to display information is

# priocntl -d [-i idtype] [idlist]

Displaying Priority Classes and Limits

You can determine which priority classes are configured on a system using the priocntl command with the −1 option, as in this Solaris 10 example:

# priocntl −1



SYS (System Class)

TS (Time Sharing)

Configured TS User Priority Range: −60 through 60

IA (Interactive)

Configured IA User Priority Range: −60 through 60

FX (Fixed priority)

Configured User Priority Range: 0 through 60

The output in this example shows that there are three priority classes defined on this system: the System Class, the Time Sharing Class, and the Real Time Class. The allowable range of tsupri values is −20 to 20, and the maximum allowable rtpi value is 59.

The /proc File System

The /proc file system is a very useful directory structure for the system administrator. It is a virtual file system-residing in memory-that is created each time the system is booted. The /proc directory structure provides an easy method of accessing information about the state of the kernel, the attributes of the machine, the states of individual processes, and more. As an example the ps and cat commands use the contents of /proc to get process information.

There are a number of directories in the /proc file system. Some of them consist of numbers only These are the directories associated with process IDs (PIDs) of various processes running on the system. There are also directories consisting of nonnumerical names that deal with the UNIX kernel features, such as the CPU, devices, memory, interrupts, networking, and loaded modules.

An experienced system administrator can use one of the directories within the /proc file system, the /sys directory, to perform kernel tuning on the system. Since this is such a powerful capability, it’s best to understand what effect manipulating the contents of /sys will have before attempting to do so on a live system.


The notion of a process is one of the most important aspects of the UNIX system. In this chapter you learned how to monitor the processes you are running by using the ps command, and how to terminate a process using the kill command.

User-level commands allow you to specify when you would like processes to be run. You can specify when commands should be executed by using the at command. The batch command lets you defer the execution of a command, but without controlling when it is run.

Daemons (or demons) are processes that are not connected to a terminal; they may run in the background and they do useful work for a user. Several daemons are normally found on UNIX Systems. Many of these daemons are controlled by cron, which is itself run by init (PID 1). The cron command is a system daemon that executes commands at specific times.

Processes on a UNIX system are sequentially assigned resources for execution. System processes have a higher priority than all user processes. UNIX does not allow much user control of time-shared process scheduling. You can, however, influence scheduling with the nice command. Another simple way to affect scheduling is with the sleep command, which creates a process that does nothing for a specified time.

Signals are used to notify a process that an event has occurred. Each process may specify an action to be taken in response to any signal. The kernel balances the demand of multiple, concurrent processes for its resources through semaphores, which act as a traffic cop to ensure processes minimize contention among themselves.

You can control what will happen after you hang up or log off. To ensure that a process stays alive after you log off, use the nohup command.

UNIX supports real-time processes. You can use the priocntl command to change the scheduling parameters of a process to real-time.

The /proc file system is a virtual file system that provides a wealth of information about processes that are currently running on your system as well as other system parameters.

How to Find Out More

To learn more about processes in the UNIX System, consult the following references. Here are some useful books discussing how processes work in the UNIX environment:

· Bovet, Daniel P., and Marco Cesati. Understanding the Linux Kernel: From I/O Ports to Process Management. O’Reilly, 2000.

· Feiler, Jesse. Mac OS X: The Complete Reference. McGraw-Hill/Osborne, 2001.

· Levi, Bozidar. UNIX Administration: A Comprehensive Sourcebook for Effective Systems and Network Management. CRC Press, 2002.

· O’Gorman, John. The Linux Process Manager. John Wiley & Sons, 2003.

· Petersen, Richard. Linux: The Complete Reference. 5th ed. McGraw-Hill/Osborne, 2002.

· Robbins, Kay and Steve Robbins. UNIX Systems Programming: Communications, Concurrency, and Threads. 2nd ed. Pearson Education (Prentice Hall), 2003.

· Watters, Paul. Solaris 10: The Complete Reference. McGraw-Hill/Osborne, 2005.

There is a useful web page on UNIX processes from an appendix of an O’Reilly publication, Practical UNIX and Internet Security:


and some others providing a background of the concept of processes at:


· and


and a printable .PDF file describing managing processes at:


These should provide background information as well as practical information.