Chapter 10. Process management

Table of Contents
10.1. Introduction
10.2. Process basics
10.3. Advanced process management

10.1. Introduction

UNIX-like operating systems work with processes. A process is an unit the operating system schedules for CPU time and the memory manager manages memory for. Basically a process consists of program code (named text), data (used by a program) and a stack. The stack is used by the program to store variables. Programs are at least one process. A program/process can ask the system to create a new copy of itself, which is called a fork. For example, a web server could fork itself to let the new process handle a request.

A process can be parted in threads. The difference between forking a process and creating a thread is that different threads share the address space of the process. A forked process is a separate process with its own address space. Forking is more expensive in terms of memory requirement and CPU time.

A user can control a process by sending signals to the process. For example, the SIGTERM command is used to terminate a process, and the SIGHUP signal to restart a process.

10.2. Process basics

This section describes some basic commands that are used for process management.

10.2.1. ps

The ps(1) command is used to report which processes are currently active. By running ps without any parameters you can see which processes are active in the current user session. Let's look at an example:


$ ps
  PID TTY          TIME CMD
 1191 pts/2    00:00:00 bash
 1216 pts/2    00:00:00 ps

In this example the bash and ps commands are running. As you can see each process has a process ID (PID). You will need the process number if you want to send a signal to a process, for example a kill signal. The ps has many parameters to modify the output. For example, the x shows all processes without a controlling tty:


$ ps x
  PID TTY      STAT   TIME COMMAND
 1044 tty1     S      0:00 -bash
 1089 tty1     S      0:00 /bin/sh /usr/X11R6/bin/startx
 1100 tty1     S      0:00 xinit /home/daniel/.xinitrc --
 1108 tty1     S      0:00 /usr/bin/wmaker
 1113 tty1     S      0:00 sylpheed
 1114 tty1     S      0:00 /bin/sh /opt/firefox/run-mozilla.sh /opt/firefox/fire
 1120 tty1     S      0:52 /opt/firefox/firefox-bin
 1125 tty1     S      0:00 /usr/libexec/gconfd-2 20
 1146 tty1     S      0:00 xchat
 1161 tty1     S      0:00 xterm -sb
 1163 pts/0    S      0:00 bash
 1170 pts/0    S      0:00 vi proc.xml
 1189 tty1     S      0:00 xterm -sb
 1191 pts/2    S      0:00 bash
 1275 pts/2    R      0:00 ps x

Have a look at the ps(1) manual page for a summary of available parameters.

10.2.2. kill

The kill(1) sends a signal to a process. If no signal is specified the TERM signal is send, which asks a process to exit gracefully. Let's have a look at the normal mode of execution:


$ ps ax | grep mc
 1045 tty4     S      0:00 /usr/bin/mc -P /tmp/mc-daniel/mc.pwd.756
$ kill 1045
$ ps ax | grep mc
$

As you can see the ps is used to look for the mc process. There is one occurrence of mc running with PID 1045. This process is killed, and the second ps command shows that the process is indeed terminated.

As we said earlier the kill command can also be used to send other signals. The kill -l displays a list of signals that can be sent:


 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     17) SIGCHLD
18) SIGCONT     19) SIGSTOP     20) SIGTSTP     21) SIGTTIN
22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO
30) SIGPWR      31) SIGSYS

The SIGKILL signal is often used to kill processes that refuse to terminate with the default SIGTERM signal. The signal can be specified by using the number as a parameter, for example, the following command would send a SIGKILL signal to PID 1045:


$ kill -9 1045

It is also possible to specify the signal without the "SIG" letters as a parameter. In the following example the SIGHUP signal is sent to the inetd to restart it:


# ps ax | grep inetd
  727 ?        S      0:00 /usr/sbin/inetd
# kill -HUP 727

10.3. Advanced process management

10.3.1. Background processes

Normally a process takes over the screen and keyboard after it is started. It is also possible to start processes as a background process, this means that the shell starts the process, but keeps control over the terminal. In most shells a process can be started as a background process by placing an ampersand (&) after the command. For example:


$ rm -rf ~/bunch/of/files &

A process that runs in the background can be brought to the foreground using the fg %<job ID> command. You can see which jobs are running, with their job numbers, using the jobs command. For example:


$ sleep 1000 &
[1] 947
$ jobs
[1]+  Running                 sleep 1000 &
$ fg %1
sleep 1000

The first command, sleep 1000 &, starts sleep in the background. sleep is a command does nothing but waiting the number of seconds that are specified as a parameter. The output of the jobs command shows that sleep is indeed running, with Job ID 1. Finally we move sleep to the foreground. As you can see, the shell will print which command is moved to the foreground.

10.3.2. Stopping processes

A process that is running can be stopped by pressing the <Control> and <z> keys simultaneously. Stopped processes can be moved to the foreground with the fg command. Running fg without any parameters moves the last process that was stopped to the foreground. Other processes can be moved to the foreground by specifying the job ID as a parameter to fg.

A stopped process can also be told to continue as a background process, by executing bg <job ID>. Executing fg without any parameter will move the last stopped process to the background.

10.3.3. Altering priorities

The Linux kernel allows a user to change the priority of a program. For example, suppose that you want to run a process that requires a lot of CPU time, but you do not want to hinder other users. In this case you can start the process with a low priority, the process will only get CPU time when there are not many other processes demanding CPU time. Or you can give processes that are important a higher priority.

GNU/Linux provides two commands to alter the priority of a process. The nice(1) command can be used to specify the priority when you are launching a process. With the renice(8) command you can alter the priority of a process that is already running. The priority is a numerical value from -20 (highest priority) to 19 (lowest priority). Let's start with an example of nice in action:


$ nice -n 19 ./setiathome

As you can see the -n parameter is used to specify the priority value. In this case the ./setiathome will have a very low priority. Be aware that only the superuser can use negative priority values. Thus, a normal user cannot give a process a higher priority, as illustrated by this example:


$ nice -n -1 nice
nice: cannot set priority: Permission denied

But it will work as the root user:


$ su -c "nice -n -1 nice"
Password: 
-1

The renice command has a somewhat different syntax. The easiest way to use it is to specify the new priority and the process ID as parameters to the renice command, as is shown in the following example:


$ renice +5 5811
5811: old priority 0, new priority 5

As with nice a non-root user cannot set negative priority values:


$ renice -5 5811
renice: 5811: setpriority: Permission denied
Note

A normal user can not increase the priority of the process beyond the default priority of 0. Such facilities could be misused by careless users. After all, the command nice is derived from being nice to the other users on the system ;^).