exec()
A Unix-like system may create the child process using fork()
, which then does not make a subsequent exec()
call. The result of this is that the parent and child processes
run the same executable. The child may communicate with the parent
using pipes. One example of a system which does this is the email
software program Exim (www.exim.org). In addition to forking without exec()
, it can also re-exec()
itself to
regain dropped root privileges.
Little or no state data passed to child
A lot of data passed to child
The first issue is where there is a little/no data passed to the
child process on the fork()
operation. Many examples
of this exist in pre/post forking of listening sockets in TCP server
applications, for example, in the MPM pre-fork module of the Apache
server. More details are available at http://httpd.apache.org/docs/2.2/mod/prefork.html.
This can be resolved by using the posix_spawn()
operation,
and passing any data using the argv
parameters or
environment variables. For more information about the posix_spawn()
operation, see http://www.opengroup.org/. Note that some argv
parameters must be used to distinguish the behaviour of the parent
process from the subsequent behaviour of the child when the main()
function is called; the behaviour of the child cannot
be identical to the parent.
Parent process forking example
P.I.P.S. equivalent
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #define NUM_OF_PROCS 5 int main(int argc, char *argv[]) { pid_t Processpid[NUM_OF_PROCS]; int I; for(I=1;i<NUM_OF_PROCS;i++) { Processpid[i] = fork(); if(Processpid[i] == 0) { printf("\r\n Child Process Inst[%d] running ***\r\n",I); //Terminate child process.5 exit(0); } else { //Wait for the child process to terminate before forking the next one. waitpid(Processpid[i],NULL,0); printf("\r\n*** Child int[%d] process finished ***\r\n",I); } } return EXIT_SUCCESS; }
#include <stdio.h> #include <stdlib.h> #include <strings.h> #include <spawn.h> #include <sys/types.h> #include <sys/wait.h> #define NUM_OF_PROCS 5 int main(int argc, char *argv[]) { if(argc != 2) { printf("\r\n One parameter is needed. \r\n"); return EXIT_FAILURE; } else { int argvAsInt = atoi(argv[1]); if(argvAsInt > NUM_OF_PROCS) { printf("\r\n parameter[%d] one is out of range \r\n",argvAsInt); return EXIT_FAILURE; } else { if(argvAsInt == 0) { //parent process. pid_t Processpid[NUM_OF_PROCS]; //executable points to the compiled version of this source. char execFileName[] = "/root/PortDoc/Example3_c/Symbian/ParentProg"; int RetVal; int I; char iAsString[2]; char* spawnedArgs[3]; spawnedArgs[0] = argv[0]; spawnedArgs[2] = NULL; for(I=1; i<NUM_OF_PROCS;i++) { //store I as a string. bzero(iAsString,sizeof(iAsString)); iAsString[0] = 0x30+I; spawnedArgs[1] = iAsString; RetVal= posix_spawn(&Processpid[i],execFileName,NULL,NULL,spawnedArgs,NULL); //wait for chid process to terminate before spawning the next. (void)waitpid(Processpid[i],NULL,0); printf("\r\n*** Child process finished ***\r\n"); } } else { //child process printf("\r\n Child Process Inst[%d] running ***\r\n",argvAsInt); //Terminate child process. exit(0); } } } return EXIT_SUCCESS; }
The second
issue is where there is too much data to be passed across to the child
process using the posix_spawn()
call.
A common work-around used in systems where fork()
is not available is to use POSIX threads, or Pthreads. These Pthreads
will execute in the same process and share their memory space, that
is, they can share the same data objects. One critical difference
between using Pthreads and fork()
is that fork()
creates copies of the parent's data objects in the
child. The copied data objects can then be modified independently
by both processes. However, when using Pthreads such data objects
are shared and extra care, such as the use of mutexes and semaphores,
is required when accessing them if their values can change.