Overview

This is a small experiment to show the life cycle of a unix process. 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.

The test program uses fork to create several children processes. Each receives an integer tag. The children then sleep for a bit then exit. The parent process sleeps after creating the children, waiting a short time after the children all exit before proceeding. The parent will then gather the output status of all the children, by repeated calls to wait, then wait again, then exit.

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.

Table of contents

The ps command

The ps command lists and gives information on the currently running processes. Definitely consult the man pages to figure out which version of ps is installed on your system. The Debian ps allows for BSD style options, if the option letters have no dash, or Posix style options, if the options letters are preceeded by a dash. I am using:

ps jfwt 1 where,

The output includes:

The Makefile

debian-32:~/nicetracing# more Makefile

CC= cc
CFLAGS= -g

FILE= processtest


all:
	${CC} ${CFLAGS} -o ${FILE} ${FILE}.c

run:
	./${FILE}

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) ;
}

The output of 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# 

The output of test program


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