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.
This section describes some basic commands that are used for process management.
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.
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
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.
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.
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
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 ;^). |