/>
fork( )
 jbwyatt.com

. unix: fork()

pid_t  fork(void)
================

DESCRIPTION
fork creates a child process that differs from the parent process only in 
its PID and PPID, and in that resource utilizations are set to 0.

RETURN VALUE
   Parent:   PID of child process is returned to the parent 
   Child:    0 is returned in the child's thread. 
   Failure:  -1 will be returned in the parent's context, no child 
             process will be created, and errno will be set

ERRORS
  EAGAIN 
  fork cannot allocate sufficient memory to copy the parent's page tables 
  and allocate a task structure for the child. 
  ENOMEM 
  fork failed to allocate the necessary kernel structures because 
  memory is tight. 



#include <stdio.h> // simplefork #include <unistd.h> // << need this int main(void) { int x = 0; fork(); x++; printf("I am process %ld and my x is %d\n", (long)getpid(), x); return 0; } -> How many kids are created here? -> How can this program report whether it is the parent or a child? -> How do we know if there is an error? -> What is the value of x in the parent? the child?

PREDICTION??

#include <stdio.h> // simplefork #include <unistd.h> // << need this #include <iostream> int main( void ) { pid_t r = fork(); printf("I am process %ld and my return code is %d\n", (long)getpid(), r); for(int i=0;i<100;i++) // 1000?? std::cout << i << " "; return 0; }

PREDICTION??

#include <stdio.h> // simplefork #include <unistd.h> // << need this #include <iostream> int main(void) { pid_t r = fork(); printf("I am process %ld and my return code is %d\n", (long)getpid(), r); if (r==0) for(int i=0;i<500;i++) std::cout << i << " "; else for(int i=0;i<500;i++) std::cout << "_" << i << "_"; return 0; }

differentiating parent & child... use return code from fork()

#include <stdio.h> #include <unistd.h> #include <sys/types.h> int main(void) { pid_t childpid; childpid = fork(); if (childpid == -1) { perror("Failed to fork"); return 1; } /* child code */ if (childpid == 0) printf("I am child %ld\n", (long)getpid()); /* parent code */ else printf("I am parent %ld\n", (long)getpid()); return 0; }

both procs report same RANDOM value of x - WHY? want each process to get it's OWN RANDOM value for random y, but it doesn't - WHY? I am process 4882 and my x is 15008 and y is 345 I am process 4883 and my x is 15008 and y is 345 could values of y ever be different?? Explain... #include <iostream> #include <cmath> #include <unistd.h> // needed for system calls using namespace std; int main() { int x, y, childpid; srand(time(0)); x = rand(); childpid = fork(); /** 2 processes here **/ srand(time(0)); // each process seeds independently (?) y = rand(); // both procs get random # here // report cout << "I am proccess " << long(getpid()) << " and my x is " << x << " and my y is " << y << endl; return 0; }
FIX!! ==== /** 2 processes here **/ change -> srand(getpid());

.. unix: fork() children vs parent

child process
-------------
   Starts processing from point of fork
   Inherits all data and values (environment, privs) from parent except:
         return value of fork()
         pid
         parent pid
         cpu usage time – zero
         no locks or alarms

=> Why do parent and child both report the same pid? #include <stdio.h> // ch3 badprocessID.c #include <unistd.h> #include <sys/types.h> int main(void) { pid_t childpid; pid_t mypid; mypid = getpid(); childpid = fork(); if (childpid == -1) { perror("Failed to fork"); return 1; } if (childpid == 0) /* child code */ printf("I am the child. ID = %ld which is the same as ID = %ld\n", (long)mypid, (long)getpid( ) ); else /* parent code */ printf("I am the parent. ID = %ld which is the same as ID = %ld\n", (long)mypid, (long)getpid( ) ); return 0; }
perror() produces a message on the standard error output, describing the last error during a call to a system or library function. If s not NULL, the argument string s is printed, followed by the message. The error number is taken from the external variable errno, which is set when errors occur but not cleared when non-erroneous calls are made. The global error list sys_errlist[] indexed by errno can be used to obtain the error message. EXAMPLE: fork error Failure: -1 will be returned in the parent's context, no child process will be created, and errno will be set ^^^^^

.. unix: fork() chain

CHAIN: children of children...
  creates a chain of n processes where n is a command line arg
--------------------------------------------------------------

#include <stdio.h>  
#include <stdlib.h>
#include <unistd.h>

int main ( int argc, char *argv[] ) {
   pid_t childpid = 0; // IMPORTANT HERE!!! 
   int i, n;
   
   /* check for # of command-line arguments which should be 
      two args: the name of the program (simplechains) and n */
   if ( argc != 2 ) /* error */
   {   
      fprintf(stderr, "Usage: %s processes\n", argv[0]);
      return 1; 
   }
   
   /* get n (number of procs) from user and loop n times */
   n = atoi( argv[1] );  
   for ( i = 1; i < n; i++ )
      if ( childpid = fork() )/* non-zero means this is parent */
         break; /* if this is parent, leave the loop and print*/

   /* parent prints each time it breaks out of loop
        last time through it prints without forking (child pid is 0)
        stderr is unbuffered (stdout is buffered) */
   fprintf( stderr, "i:%d  PID:%ld  parent ID:%ld  child ID:%ld\n",
            i, (long)getpid(), (long)getppid(), (long)childpid );
            // (long) cast on childpid caused the zero to be a '1'
   return 0; 
}

jupiter/export/home/wyatt/private/opsys/UNIXSysProg/ch3$ simplechain 4 i:1 process ID:13478 parent ID:13362 child ID:13479 (original process) i:4 process ID:13481 parent ID:13480 child ID:0 i:3 process ID:13480 parent ID:13479 child ID:13481 i:2 process ID:13479 parent ID:13478 child ID:13480 shell = 13362 i =1, proc = 13478, child =13479 i =2, proc = 13479, child =13480 i =3, proc = 13480, child =13481 i =4, proc = 13481, child =0 value of i when it leaves the loop 1 is parent of 2 2 is parent of 3 3 is parent of 4 4 has no child

.. unix: fork() fan

FAN: siblings
   creates a fan of n processes where n is a command line arg
-------------------------------------------------------------

#include <stdio.h>  // simplefan.c
#include <stdlib.h>
#include <unistd.h>

int main ( int argc, char *argv[] ) {
   pid_t childpid = 0; 
   int i, n;
 
   if ( argc != 2 ){ /* check for # of command-line arguments which should be 
                        two args: the name of the program (simplechains) and n */
      fprintf( stderr, "Usage: %s processes\n", argv[0] );
      return 1; 
   }     
   n = atoi( argv[1] );  /* get the number of procs from user */
   for ( i = 1; i < n; i++ )
      if ( childpid = fork() <= 0 ) /* non-zero means this is parent */
         break; /* if this is child, leave the loop and print*/

   /* the child prints each time it breaks out of loop and the 
      last time through it prints without forking */
   fprintf( stderr, "i:%d  PID:%ld  parent ID:%ld  child ID:%ld\n",
            i, (long)getpid(), (long)getppid(), (long)childpid );
            // (long) cast on childpid caused the zero to be a '1'          
   return 0; 
}

12177 (i=4) 12178 (i=1) 12179 (i=2) 12180 (i=3)
i:1 process ID:12178 parent ID:12177 child ID:0 i:3 process ID:12180 parent ID:12177 child ID:0 i:2 process ID:12179 parent ID:12177 child ID:0 i:4 process ID:12177 parent ID:18743 child ID:12180 (original process)