Process Management
Objective
- Introduce the concept of a process in an operating system.
- Show a dynamic real-time view of the running operating system.
- Set and adjust process priority using
nice
andrenice
. - Send signals to processes using
kill
. - Understand the
fork
system call and use it to create processes. - Differentiate between parent and child processes.
- Use
getpid
andgetppid
system calls for process identification.
Summary
exit
htop
jobs
kill
nice
pgrep
ping
ps
renice
sleep
top
xargs
0
NULL
fork()
getpid()
getppid()
perror()
Environment
- Almost everything in Unix is either a file or a process.
- In computing, a process is an instance of a computer program that is being executed. It contains the program code and its current activity.
- A process is identified by a unique PID (process identifier). A process could be made up of multiple threads, that are lightweight processes, of execution that execute instructions concurrently.
- A file is a collection of data. They are created by users using text editors, running compilers, and other means.
- The output of one utility or program can be sent to a file, or as input to another utility or program.
- Many utilities may take their input from files other than the keyboard.
Command-Line Execution
- The shell looks for a command in the following order:
- alias
- built-in
- function
- search path
- If the command is located, the shell creates a new process to execute the command.
- The shell waits while the command executes.
- The shell wakes up when the command is done executing and re-issues the prompt.
Processes
- A process is an instance of an executing program.
- Processes are created by a parent process in two steps:
- The parent process clones itself (
fork
), and - The child process replaces the parent program (
exec
).
- The parent process clones itself (
- Each process has a unique number assigned to it (PID).
- Every process has two parts:
- program (image), and
- environment:
- inherited from parent.
- includes standard files for input, output, and error.
Listing Processes
Use ps
to see the status of your processes and their PID’s. The options are:
Option | Description |
---|---|
-e | Every process on the system |
-f | Full listing of process details |
-l | Long listing of process details |
-u username | Processes belonging to a certain user |
Example 1
> ps
PID TTY TIME CMD
3147 pts/0 00:00:00 bash
3511 pts/0 00:00:00 ps
The abbreviations in the above example output are:
PID
is the identification number for the process.TTY
is the terminal console to which the process belongs.TIME
is the total CPU time used by the process.CMD
is the command line being executed.
You can use the manual to know more about the ps
command options: man ps
.
Exercise 1
Run the following commands:
ps
sleep 15
ps -e
ps -f
sleep 20
ps -e
ps -u root
ps -ef | more
System Initialization
init
process: The first process to run in your system. init
is short for initialization. Typically, it has a PID of 1
but this may vary based on the implementation. This process is responsible for starting services when booting, stopping them when shutting down, and supervising them while the system is running. There are many implementations of the init
(opens in a new tab) process. Examples of that are systemd
(opens in a new tab), SysV
, Upstart
, OpenRC
, runit
, and many others.
Realtime View
The top
command provides a dynamic real-time view of the processes of an operating system. The top
command can display system summary information as well as a list of all processes currently being managed by the kernel, sorted by CPU usage.
The command-line syntax for top
consists of top -option
, where the common options are:
Option | Description |
---|---|
-p | Monitor only processes with specified process identifiers. This option can provide a comma delimited list with up to 20 PID’s. |
-u | Monitor only processes with an effective user name matching the one given. |
-i | Include processes that are idle or zombie. |
-H | All individual threads will be displayed. |
-S | Each process is listed with the CPU time that it and its children have used. |
The output of the top
command contains the following fields:
Field | Description |
---|---|
PID | Process identifier |
PPID | Parent process identifier |
USER | Process owner username |
TTY | Name of controlling terminal |
PR | Process priority |
NI | Nice value (adjustable priority). A negative value means high priority, whereas a positive value means low priority. |
%CPU | The elapsed CPU time since the last screen update expressed as a percentage of total CPU time. |
TIME | The total CPU time used by the process since it started |
TIME+ | Same as TIME, but with more accuracy to a hundredth of a second. |
%MEM | A process’s currently used share of available physical memory. |
VIRT | The total amount of virtual memory used by the process, in kB. VIRT = SWAP + RES |
SWAP | The swapped out portion of a process’s total virtual memory, in kB. |
RES | The non-swapped (resident) physical memory a process has used, in kB. |
SHR | The amount of memory shared by the process and other processes, in kB. |
nDRT | The number of dirty pages that have been modified since were last written to the disk. |
nFLT | The number of major page faults that have occurred for process. A page fault occurs when a process attempts to read from or write to page that is not currently present in its address space. |
S | The status of the process can be one of: D = uninterruptible sleep R = running S = sleeping T = traced or stopped Z = zombie |
COMMAND | Display the command line used to start a task or the name of the associated program. |
Note: You can also install and use the htop
command, which provides an interactive dynamic view of the processes.
Process Priority
The kernel uses separate priority ranges for normal and real-time tasks. For normal tasks a priority range (or nice value) of -20
to +19
is used. Lower nice corresponds to higher priority. In other words the task is being less nicer to other tasks in the system. For real-time tasks a priority range of 0
to 99
is used. In this case a higher number indicates higher priority. RT
is short for real-time priority.
Typically, PR = 20 + NI
, where PR
is the priority and NI
is the nice value. Internally, the kernel uses a single range (0
–139
) that maps each of the above two ranges. In this range lower value means higher priority. The user-space NI
values, -20
–19
, are mapped to 100
–139
.
The Completely Fair Scheduler (CFS) is a process scheduler which handles CPU resource allocation for executing processes, and aims to maximize overall CPU utilization while also maximizing interactive performance. The Earliest Eligible Virtual Deadline First ( EEVDF) is a real-time scheduler that is based on the Earliest Deadline First (EDF) algorithm. (CFS) replaced by the EEVDF scheduler in Linux 6.6 and later.
The nice
command is used to run a given process with its scheduling priority adjusted. The renice
command is used to alter or change the scheduling priority of a running process.
You can run a program (process) with its default priority adjusted by using the nice
command followed by the priority number then the program name, for example:
nice sleep 5m &
This will run the sleep
process with adjusted priority. Since the priority is not specified in this example, it will be increased by 10
(the process will run with less priority) from the default value (usually 0
).
The priority can be explicitly incremented or decremented using, for example:
nice -n 15 sleep 5m &
nice -n -10 sleep 5m &
To set a process to have a different priority, first find the PID number using the ps
or pgrep
commands, then use the renice
command:
renice 5 -p 3314
This will set the process, with PID 3314
, to a priority of -20
. Note that only the root user can specify negative priority values.
Process Control
You can kill a process by using the kill
command and the PID number, for example:
kill 1721
You can also suspend, resume, and restart processes by sending them various signals as in the following examples:
Description | |
---|---|
kill -STOP 1721 | Stops (suspends) process 1721 by sending the STOP signal to the process. This process will still be on the task list. |
kill -CONT 1721 | Continues process 1721 causing it to resume. The CONT signal is sent to the process. |
kill -TERM 1721 | Terminates process 1721 by sending the TERM signal to the process. This process will no longer show up on the task list if it is actually terminated. The terminated process cannot be continued. |
kill -HUP 1721 | Stops then restarts process 1721 . This is usually done when a process is not working properly or the configuration files for that process have been changed. This command sends the HUP signal to the process which means hang-up. |
Try the kill options with the following command:
ping 127.0.0.1 > output &
You can use pgrep
to find the PID of a process by its name, for example: pgrep ping
. The output of this command can be used with the kill
command, for example: pgrep ping | xargs kill
. The xargs
command is used to build and execute command lines from standard input.
The pkill
command, which sends signals to processes based on names and other attributes, can also be used: pkill ping
.
Signals
Standard signals range from 1
to 31
, the default signal is 15
(SIGTERM
). Signal number 0
, called the null signal, is generally not used but the kill
command uses it as a special case: No signal is sent but it can be used (rather unreliably) to check if the process still exists.
In your terminal, ^C
sends a SIGINT
(2
) to interrupt a process, ^D
sends a SIGTSTP
(20
) to suspend a process, and ^\
sends a SIGQUIT
(3
) to quit a process. All the supported signals can be listed using kill -l
.
There are some processes that are protected and can catch or ignore signals, therefore to ensure a guaranteed kill we use the signal number 9
(SIGKILL
). To illustrate a simple sure kill
command, try the following:
kill -9 terminal_PID # a sure kill, your terminal will be closed
Note: You cannot kill a process of another user.
Background Processes
- The shell normally waits for its child process to terminate before returning to prompt.
- Long running jobs that do not require user input can be run in the background.
- A process may be in the foreground, in the background, or be suspended.
- foreground process: The shell does not return the prompt until the current process has finished.
- background process: The shell returns immediately to the prompt while the process is running in the background. Useful for long processes so that we can continue to execute other tasks.
- suspended process: The process is stopped by
^Z
while executing.
- To background a process, type an
&
at the end of the command line:- The shell returns a job id and a process id.
- The output and error is still directed to your terminal.
- Use redirection to send
stdout
andstderr
to files.
- Use
jobs
to list foreground, background processes, and their job number. - Background and foreground processes can be terminated with
kill PID
. - Stubborn processes that will not die gracefully can be killed using
kill -9 PID
.
Example 2
sleep 10
sleep 400 &
ps -e
find / -name core > list 2> /dev/null &
jobs
Exercise 2
-
List your current processes using
ps
. -
Start a new shell using
sh
. -
List your current processes again. Notice the new process you created, then exit from
sh
usingexit
. -
List your current processes again. The
sh
shell process no longer exits. -
To view more detailed information about a process, use the
-f
(full details) option, as in,ps -f
. -
To list all the processes that are currently running on the system, use
ps -ef | more
. -
Execute the following commands to start a number of shell processes:
sh bash sh
-
Execute
ps -f
. Follow the PID and PPID relationship to determine the processes and the order in which they were started. -
Type
exit
or^D
until you have returned to your login shell;useps
to check. -
Return to your home directory and execute
sleep 10
. The shell process will normally wait or sleep until its child has completed its task and has terminated. -
Execute
sleep 10 &
. The shell responds with a job and a process id. -
Execute
ps
to list your processes. -
Execute
jobs
to list all of your background processes. -
Execute the following commands and note their PID numbers:
sleep 1000 & find / -name core > ~/mylist 2> /dev/null &
-
List your processes using
ps
. -
Identify the PID of the
find
process and terminate it usingkill PID
. -
Identify the PID of your login shell process and terminate it using
kill PID
. -
Try to forcefully kill using
kill -9 PID
. What happens?
Process Creation
fork
-
A system call that creates a new process under the operating system.
-
Process Control Block (PCB): a data structure that represents one process.
-
When n
fork
calls are executed in sequence, we end up with 2n processes. This can be visualized using a full binary tree for threefork()
calls, resulting in 23 = 8 processes, as follows:This sequence of n
fork()
calls can also be represented using the following self-similar tree:
Differences
- Different PID’s for parent and child.
- In the parent,
fork()
returns the PID of the child process if a child process is created. In the child, it always returns0
. - Separate copies of all data, including variables with their current values and the stack.
- Separate program counters (PC) indicating where to execute next; originally both have the same value but they are thereafter separate.
- After
fork()
, the two processes do not share their variables.
Implementation
fork()
is a system call that creates a new PCB.- It copies most information from the current process’s PCB into the next free location in the process table.
- The parent and child processes will now both be ready to execute.
- One can be left/placed in the
RUNNING
state and the other in theREADY
state. - Henceforth, both will take turns in using the processor, along with all the other processes.
- Which one is chosen to run first, depends on the scheduler of the operating system.
- A call to
fork()
returns:- The
pid
of the new child process to the parent process; this is equivalent to telling the parent the name of its child. 0
to the child process.- A negative number (
-1
) if there is an error, that is,fork()
failed because a new process could not be created.
- The
Example 3
Compile and run the following program:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h> /* defines fork() and pid_t */
int main(void) {
printf("Just one process so far\n");
printf("Forking...\n");
pid_t pid;
pid = fork();
if (pid < 0) {
printf("fork failed\n");
}
if (pid == 0) {
printf("I'm the child\n");
}
if (pid > 0) {
printf("I'm the parent with child ID = %d\n", pid);
}
return EXIT_SUCCESS;
}
Exercise 3
Write a program to demonstrate that the program variables in a parent process and a child process have the same initial values but are independent of each other, that is, the child receives a copy of the variables.
Example 4
Compile and run the following program, which demonstrates the use of the getpid()
and getppid()
system calls:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
printf("Original process ID = %d\n", getpid());
printf("Forking...\n");
pid_t pid = fork();
if (pid != 0) {
printf("I am the parent process with PID = %d and my child's PID = %d\n",
getpid(), pid);
} else {
/* pid is zero, so child process is running this part */
printf("I am the child process with PID = %d and PPID = %d\n", getpid(),
getppid());
sleep(5); /* allows the parent to execute first */
}
/* both processes are running this part */
printf("PID = %d terminated\n", getpid());
return EXIT_SUCCESS;
}
The getpid()
system call returns the process’s identifier and the getppid()
system call returns the parent process’s identifier.
Exercise 4
Write a C program that will fork a new process. The parent side has to calculate and print the average of all positive numbers of an array composed of 6 elements entered by the user, while the child process has to calculate and print the product of all negative numbers of the same array. Compile and run your program.