Unix Fork example:

Musings

Home

UNIX Notes



Comments:


Code:

#include <stdio.h>   // used in printf
#include <stdlib.h>  // used in atoi and wait
#include <unistd.h>  // used in fork and getpid
#include <time.h>    // used in nanosleep

// File: spawn.c
// Date: Oct 8, 2017
// Author: Nicholas Duchon
// Purpose: demonstrate process interleaving using fork()
// References: a variety of net searches

// stuff for nanosleep control structure
// uses time.h declarations
struct timespec tim0, tim1, tim2;

void pr (int v, int max) {
   int j;

   // wait before starting looping
   nanosleep (&tim0, &tim2);

   for (j = 0; j < max; j++) {
      printf ("-- %3d -- %c: %d\n", v, 'A'+v, j);
      nanosleep (&tim1, &tim2);
      if (j%100 == 99)
         printf ("\n");
   } // end printing some different stuff in each child

} // end pr

int main (int argc, char *argv[]) {
   // wait before starting looping
   // makes it possible to start some/all processes before any loop
   tim0.tv_sec  = 2;
   tim0.tv_nsec = 0;

   // wait on each iteration
   // lets processes interleave
   // otherwise processors are so fast that interleaving hard to detect
   tim1.tv_sec  = 0;
   tim1.tv_nsec = 100000;

   pid_t pid;         // process id, used to tell child 0 from parent > 0
   int i;             // index in for loop used to create max children
   int max = 10;      // number of iterations for each child
   int nChildren = 5; // how many children to create

   if (argc > 1)
      nChildren = atoi (argv[1]);
   if (argc > 2)
      max = atoi (argv[2]);

   for (i = 0; i <= nChildren; i++) {
      pid = fork();
      if (pid == -1) {
            /* error handling here, if needed */
         return 1;
      }
      if (pid == 0) {
         // can make decisions based on i at this point, for example
         printf("Starting Child: %3d PID: %d\n",i, getpid());
         pr (i, max);
        
         // do not go back into the for loop in a child process
         // could also do a return (0) here as well
         break;
      } // in children
      else {
        // do something in main before next fork?
        // wait is probably not what you want to do here
      } // in parent
   } // end for

   // The following will wait until all child processes finish
   // otherwise, end of parent will kill all children even if they are not finished
   wait (NULL);

   return 0;
} // end main


Nicholas Duchon, Oct 8, 2017