In 1632, Galileo puts Salviati, Sagredo, and
Simplicio into a four-day conversation in Dialogo sopra i due massimi sistemi del mondo.
This characters: Sage, Simon and Simple, were AI generated for similar dialogs
concerning operating systems principles.
This is a small experiment to show the life cycle of a unix process.
The unix book by
Maurice Bach,
and reproduced on this page, gives a highly detailed state transition diagram for a unix
process. The conceptual outline is simpler.
A Unix process is created in the idle state,
and is then moved between ready to run, running, and possibly waiting
(or sleeping), until it exits and becomes a zombie.
Once a
process, usually the parent process, reaps the exit status of the zombie, then
the process is destroyed.
Because the number of logical threads exceeds the number of physical threads, the logical
threads share time slices on the physical threads, interleaving with enough frequency so
that the logical threads appear to run simultaneously. When the thread is running on
a physical thread it is in the run state, and when it is not on a physical thread, and
making no computational progress, it is in the ready state.
A logical thread might be in a state where it has nothing to do until some event
occurs. For instance, in I/O wait. The thread is processing input and the input is
being retrieved. The ask for the I/O is made in the running state, then the thread
goes to the wait state, with some software magic that connects the wait to the I/O task.
The completion of the task, e.g. the delivery of data, returns the thread
to the ready state.
Testing and visualizing Unix fork and waits
-
The test program uses fork to create several children
processes. Each receives an integer tag.
-
The children report their initiation, then sleep for a bit before exiting.
-
The parent process then gathers the exit status of all the children,
by repeated calls to wait, reports the exit of each child,
and then itself exits.
Using the ps command, we will see the children all in the wait
states, then in their zombie states, then only the parent in the wait, with
the children processes gone, and finally back to the shell. The parent
relationship of the process includes how bash is the parent of
make, and make is the parent of the test program.
It also shows that I logged in as a normal user, UID 1000, but ran these programs
as root, so there is an su and a second bash in the
chain of processes.
The ps command options I use are,
where,
- the j option includes a lot more columns of information,
- the f option displays the task's parent child relationship using a tree format
(f for forest),
- the w option enables wide output, that extends beyond a resumed screen with,
- the t option will limit output to those processes holding the controlling terminal
which is named following the option.
The output includes:
- PID, the process ID,
- PPID, the parent PID,
- PGID,the process group ID,
- SID, the session ID,
- TTY, the device number of the controlling tty
- TPGID, controlling tty process group ID
- STAT, the process status,
- TIME, the consumed processor time,
- COMMAND, the name of the command,
The test program
debian-32:~/nicetracing# more processtest.c
/*
* author: burt rosenberg
* created: 12 sept 2010
* last update: 12 sept 2010
*/
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#define LONG_SLEEP 20
#define SHORT_SLEEP 10
#define N_CHILD 4
int main(int argc, char * argv []) {
int i = 0 ;
pid_t pid ;
int exit_status ;
printf("Parent: starts\n") ;
for (i=1;i<N_CHILD;i++ ) {
if ( !(pid = fork()) ) {
/* child */
printf("Child: starting %d\n", i ) ;
fflush(NULL) ;
sleep(SHORT_SLEEP) ;
printf("Child: ending %d\n", i ) ;
fflush(NULL) ;
exit(i) ;
}
printf("Parent: forked child %d with pid %d\n", i, pid ) ;
fflush(NULL) ;
}
sleep(LONG_SLEEP) ;
printf("Parent: reaps ...\n") ;
for (i=1;i<N_CHILD;i++) {
pid = wait(&exit_status) ;
printf("Parent: child %d has exit code %d\n",
pid, WEXITSTATUS(exit_status)) ;
}
sleep(SHORT_SLEEP) ;
printf("Parent: exits\n") ;
exit(0) ;
}
A run of the test program
debian-32:~/nicetracing# make
cc -g -o processtest processtest.c
debian-32:~/nicetracing# make run
./processtest
Parent: starts
Child: starting 1
Parent: forked child 1 with pid 2694
Child: starting 2
Parent: forked child 2 with pid 2695
Child: starting 3
Parent: forked child 3 with pid 2696
Child: ending 1
Child: ending 2
Child: ending 3
Parent: reaps ...
Parent: child 2694 has exit code 1
Parent: child 2695 has exit code 2
Parent: child 2696 has exit code 3
Parent: exits
debian-32:~/nicetracing#
Process tree during run
debian-32:~/nicetracing# ps jfwt 1
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2467 2468 2468 2468 pts/1 2482 Ss 1000 0:00 -bash
2468 2481 2481 2468 pts/1 2482 S 0 0:00 \_ su
2481 2482 2482 2468 pts/1 2482 S+ 0 0:00 \_ bash
debian-32:~/nicetracing# ps jfwt 1
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2467 2468 2468 2468 pts/1 2692 Ss 1000 0:00 -bash
2468 2481 2481 2468 pts/1 2692 S 0 0:00 \_ su
2481 2482 2482 2468 pts/1 2692 S 0 0:00 \_ bash
2482 2692 2692 2468 pts/1 2692 S+ 0 0:00 \_ make run
2692 2693 2692 2468 pts/1 2692 S+ 0 0:00 \_ ./processtest
2693 2694 2692 2468 pts/1 2692 S+ 0 0:00 \_ ./processtest
2693 2695 2692 2468 pts/1 2692 S+ 0 0:00 \_ ./processtest
2693 2696 2692 2468 pts/1 2692 S+ 0 0:00 \_ ./processtest
debian-32:~/nicetracing# ps jfwt 1
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2467 2468 2468 2468 pts/1 2692 Ss 1000 0:00 -bash
2468 2481 2481 2468 pts/1 2692 S 0 0:00 \_ su
2481 2482 2482 2468 pts/1 2692 S 0 0:00 \_ bash
2482 2692 2692 2468 pts/1 2692 S+ 0 0:00 \_ make run
2692 2693 2692 2468 pts/1 2692 S+ 0 0:00 \_ ./processtest
2693 2694 2692 2468 pts/1 2692 Z+ 0 0:00 \_ [processtest] <defunct>
2693 2695 2692 2468 pts/1 2692 Z+ 0 0:00 \_ [processtest] <defunct>
2693 2696 2692 2468 pts/1 2692 Z+ 0 0:00 \_ [processtest] <defunct>
debian-32:~/nicetracing# ps jfwt 1
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2467 2468 2468 2468 pts/1 2692 Ss 1000 0:00 -bash
2468 2481 2481 2468 pts/1 2692 S 0 0:00 \_ su
2481 2482 2482 2468 pts/1 2692 S 0 0:00 \_ bash
2482 2692 2692 2468 pts/1 2692 S+ 0 0:00 \_ make run
2692 2693 2692 2468 pts/1 2692 S+ 0 0:00 \_ ./processtest
debian-32:~/nicetracing# ps jfwt 1
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
2467 2468 2468 2468 pts/1 2482 Ss 1000 0:00 -bash
2468 2481 2481 2468 pts/1 2482 S 0 0:00 \_ su
2481 2482 2482 2468 pts/1 2482 S+ 0 0:00 \_ bash