More On Processes

Process Status

As defined earlier, a process is an instance of a running program. Each time a program is run, a process is created (typically) with the same name as the program itself. Processes have the concept of a lifetime associated with them. Processes come to life, or are said to be born as a program is loaded and begins execution. Processes remain alive while the program continues execution (processes, however can have different states of life). Processes ceast to exist and are said to die as the running program terminates (either normally or abnormally).

As was also mentioned, processes have a parent which created them. Similarly, when a process is created, it is created as a child process, with the process responsible for its creation being its parent. When a process creates a child process, it is said to have spawned a child. Every process on a Unix system must have a parent (again, except the very first one), since "orphaned" processes are not allowed. Also, all processes on a Unix system can be linked to the single initial process.

Each process will have many attributes associated with it. A processes attributes are stored in a structure memory which is called a Process Control Block, or PCB. Each indiviual process will have a PCB associated with it. Some of these attributes include PID, PPID, priority, ownership, state, etc. The diagram below shows the parent-child relationship, as well as the PCB of each process.

To examine the actual status of processes on a Unix system, the ps command will be used along with several of its options. By simply runnig the ps command without any options, one can observe the following:
	$ ps [Enter]
  	PID   TTY          TIME  CMD
	30758 pts/0    00:00:00  ksh
	30891 pts/0    00:00:00  ps
In this output, two running programs are listed, the ksh (parent) process and the ps (child) process. Along with this is displayed the PID of each as well as the TTY (connected terminal id) and the cumulative execution time. Only two are listed since these two processes are the only two belonging to this user id (uid) and this TTY.

A bit more information can be viewed using the -x option with ps (note that not all options will work on all Unix implementations; see the ps man page on your system) as follows:

 	$ ps -x [Enter]
  	PID   TTY      STAT   TIME  CMD
	30758 pts/0    S      0:00  -ksh
	31043 pts/0    R      0:00  ps -x
In this output, we see all information from above as well as an additional field labeled STAT which indicates the process status. What do the S and R status values indicate? Recall what happens to the parent when a child process executes. In general, the possible process states are:
	D   uninterruptible sleep (usually IO)
	R   runnable (on run queue)
	S   sleeping
	T   traced or stopped
	Z   a defunct ("zombie") process
Also notice that the PID of the ksh processes is the same in both output displays (30758) but the two ps command PIDs differ (30891 & 31043). Can you explain this?

All of the processes on a Unix system can be listed using several options as follows:

 	$ ps -eaf [Enter]
	UID        PID  PPID  C STIME TTY          TIME  CMD
	root         1     0  0 Oct12 ?        00:00:04  init
	root         2     1  0 Oct12 ?        00:00:00  [keventd]
	root         3     1  0 Oct12 ?        00:00:00  [kapm-idled]
	root         4     0  0 Oct12 ?        00:00:00  [ksoftirqd_CPU0]
	root         5     0  0 Oct12 ?        00:00:00  [kswapd]
	root         6     0  0 Oct12 ?        00:00:00  [kreclaimd]
	root         7     0  0 Oct12 ?        00:00:00  [bdflush]
	root         8     0  0 Oct12 ?        00:00:00  [kupdated]
	root         9     1  0 Oct12 ?        00:00:00  [mdrecoveryd]
	root        13     1  0 Oct12 ?        00:00:01  [kjournald]
	root        88     1  0 Oct12 ?        00:00:00  [khubd]
	root       193     1  0 Oct12 ?        00:00:00  [kjournald]
	root       649     1  0 Oct12 ?        00:00:00  syslogd -m 0
	ntp        749     1  0 Oct12 ?        00:00:00  ntpd -U ntp
	root       785   749  0 Oct12 ?        00:00:00  ntpd -U ntp
	root       805     1  0 Oct12 ?        00:00:02  /usr/sbin/sshd
	lp         864     1  0 Oct12 ?        00:00:00  lpd Waiting  
	root       892     1  0 Oct12 ?        00:00:00  sendmail: accepting connections
	root       939     1  0 Oct12 ?        00:00:00  gpm -t ps/2 -m /dev/mouse
	root       957     1  0 Oct12 ?        00:00:00  crond
	xfs       1027     1  0 Oct12 ?        00:00:00  xfs -droppriv -daemon
	daemon    1063     1  0 Oct12 ?        00:00:00  /usr/sbin/atd
	root      1086     1  0 Oct12 tty1     00:00:00  /sbin/mingetty tty1
	root      1087     1  0 Oct12 tty2     00:00:00  /sbin/mingetty tty2
	root      1088     1  0 Oct12 tty3     00:00:00  /sbin/mingetty tty3
	root      1089     1  0 Oct12 tty4     00:00:00  /sbin/mingetty tty4
	root      1090     1  0 Oct12 tty5     00:00:00  /sbin/mingetty tty5
	root      1091     1  0 Oct12 tty6     00:00:00  /sbin/mingetty tty6
	root     30757   805  0 15:21 ?        00:00:00  /usr/sbin/sshd
	mthomas  30758 30757  0 15:21 pts/0    00:00:00  -ksh
	mthomas  30845 30758  0 16:41 pts/0    00:00:00  ps -eaf
Notice that the owner of most of these processes is root. Notice also that both the PID and the PPID are listed in this output. Looking at this output dissected, one should be able to trace the ancestry of the ps command:
	$ ps -eaf [Enter]
	UID         PID  PPID  C STIME TTY          TIME CMD
	root          1     0  0 Oct12 ?        00:00:04 init
	root        805     1  0 Oct12 ?        00:00:01 /usr/sbin/sshd
	root      30757   805  0 15:21 ?        00:00:00 /usr/sbin/sshd
	mthomas   30758 30757  0 15:21 pts/0    00:00:00 -ksh
	mthomas   30845 30758  0 15:29 pts/0    00:00:00 ps -eaf
You can see the process id of the ps process is 30845, and its parent is PID 30758. Process number 30758 is the ksh process, and its parent is process 30757. Process 30757 is sshd (a secure shell client 1) and its parent is PID 805. Process 805 is sshd (a secure shell server) whose parent is PID 1, which leads us to our venerable grandparent process, init. 2

There is another way to view the system process hierarchy, and that is using the command pstree. This command gives you a top-down view of the process tree as follows:

	$ pstree [Enter]
This is an alphabetical listing, with all processes being connected to init. Make sure you can identify the parent-child connection from the pstree command as describe in the ps output above.

1 This connection is being made from a Win PC with a ssh client to a Linux installation via a ssh server connection, thus the 2 ssh processes.

2 As mentioned previously, since the original publication of this e-text, the init process has been replaced in some Linux distributions by the systemd process, also having PID 1. This has become somewhat controversial, and has been described as a violation of the Unix philosophy. More on the systemd process here. [Wikipedia contributors]

More With fork and exec

As mentioned earlier, processes are created using two Unix system calls, namely fork and exec.

The fork system call creates a new process by duplicating the calling process (i.e. the parent). This new process differs from the parent process only in its new PID and the PPID pointing back to the parent. Following a fork system call, 2 processes will co-exist (the parent and the child). Often coupled with fork is the exec system call. The exec system call immediately replaces or overlays the newly created child process (when used with fork), which includes inheriting the process id of the process it replaced. The standard method for creating a new process is to use fork to make a copy of the existing process, then using exec to overwrite the copy with the new (child) process. This is commonly refered to as the fork-exec call sequence.

Following are examples of fork and exec in action. In the first example, initially a Korn shell is present, displayed by the ps command. Next the bash command is entered, which uses a fork call to clone the (ksh) parent, then overwriting the child (via exec) with the bash process, resulting in both a Korn shell parent and a bash shell child. Thus when the exit command is entered the child dies leaving only the Korn shell parent.

	$ ps -x
	 7540 pts/0    S      0:00 -ksh
	 7573 pts/0    R      0:00 ps -x
	$ bash
	$ ps -x
	 7540 pts/0    S      0:00 -ksh
	 7574 pts/0    S      0:00 bash
	 7586 pts/0    R      0:00 ps -x
	$ exit
	$ ps -x
	 7540 pts/0    S      0:00 -ksh
	 7594 pts/0    R      0:00 ps -x
In the second example, the same Korn shell is present as above. When the bash shell is exec'd (without a fork), this leaves only a bash process and no Korn shell process. Note the PID of the new bash shell is the same as the overwritten Korn shell.
	$ ps -x
	 7540 pts/0    S      0:00 -ksh
	 7599 pts/0    R      0:00 ps -x
	$ exec bash
	$ ps -x
	 7540 pts/0    S      0:00 bash
	 7611 pts/0    R      0:00 ps -x

Process Control

Running processes, especially those that do not complete quickly, are often referred to as running jobs, or just jobs. For jobs that do not complete quickly (in a second or two), these sometimes need special care so that other work can be done efficiently. Unix provides the capability to allow processes (jobs) to run in the foreground where they can allow user interaction, or the background where they can run uninterrupted. By default, jobs run in the foreground and do not return control of the terminal until completed.

Terminate a process

If a process is running, and the terminal (i.e. tty) that started its execution is available, the simple key sequence to terminate a process is [Ctrl-c]. This will result in the process being immediately terminated.

If there is not access to the starting tty, and you wish to terminate a process (i.e. remotely), the command to do this is:

	kill signal pid
where the signal is optional.The signal can be an actual Unix signal or can be a numeric representation of a signals value. Some of the common named Unix signals and their corresponding numeric ids are:
Thus, you can terminate a process in the following ways:
	kill pid		# default signal of SIGTERM
	kill -KILL pid		# use of SIGKILL signal
	kill -9 pid		# also KILL signal
Some processes will ignore certain signals, for example, if you try to kill your shell with the default TERM signal, this will be ignored by the shell. Typically when you want to kill a process, you really want to terminate it and the -9 signal is the easiest to remember.

Suspend a process

Suspending a process is done with key sequence [Ctrl-z]. Once this command is entered, the process becomes a suspended (stopped) process, as follows:

	$ vi foo [Enter]
	[1] + Stopped              vi foo 
	$ ps -x [Enter]
	 2876 pts/0    S      0:00 -ksh
	 2941 pts/0    T      0:00 vi foo
	 2946 pts/0    R      0:00 ps -x
Move a process/job to the background

To move a suspended (stopped) process to the background, you use the bg command. This will allow the suspended job to execute in the background.

Move a background process/job to the foreground

To move a background process to the foreground, you use the fg command. This will continue the execution of the job in the foreground.

Start a job to execute as a background process.

To start a job in the background, you simply follow the command with the ampersand (&) character. This is analogous to suspending the job and issuing the bg command. When a job is started in the background, control of the terminal will return immediately. This is especially useful when starting programs that run in their own GUI based window, such as browsers and hardware monitors, for example:

	$ firefox & [Enter]
List active jobs

To list active jobs, you simply use the jobs command. The jobs command will show all active jobs for the current user.

	$ jobs [Enter]
	[1] + Running              du /  
	[2] - Running              loop_program 
	[3] - Running              cc configs.c
Notice the numbers enclosed within the brackets, []. This indicates the order of the job, that is the nth job in the job queue. To operate on a specific job, specify the job number preceded by the percent character. Thus to bring the 2nd job to the foreground, the command would be:
	$ fg %2 [Enter]

Command Summary

©2019, Mark A. Thomas. All Rights Reserved.