<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License
"Eclipse Public License v1.0" which accompanies this distribution,
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
Nokia Corporation - initial contribution.
Contributors:
-->
<!DOCTYPE concept
PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept id="GUID-545DA961-217E-49CA-A90E-7A41E2C03A99" xml:lang="en"><title>Forking
without <codeph>exec()</codeph></title><shortdesc>A Unix-like system may create the child process using <codeph>fork()</codeph>,
which then does not make a subsequent <codeph>exec()</codeph> 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 <codeph>exec()</codeph>, it can also <codeph>re-exec()</codeph> itself
to regain dropped root privileges.</shortdesc><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>The issues that such systems encounter when porting to P.I.P.S. fall into
two categories: <ul>
<li><p><b>Little or no state data passed to child</b></p></li>
<li><p><b>A lot of data passed to child</b></p></li>
</ul></p>
<section><title>Little or no state data passed to child</title><p>The first
issue is where there is a little/no data passed to the child process on the <codeph>fork()</codeph> 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 <xref href="http://httpd.apache.org/docs/2.2/mod/prefork.html" scope="external">http://httpd.apache.org/docs/2.2/mod/prefork.html</xref>. </p><p>This
can be resolved by using the <xref href="GUID-E7C4DE71-BC5B-34AE-ACB3-C34A0DB1FC16.dita"><apiname>posix_spawn()</apiname></xref> operation, and
passing any data using the <codeph>argv</codeph> parameters or environment
variables. For more information about the <codeph>posix_spawn()</codeph> operation,
see <xref href="http://www.opengroup.org/" scope="external">http://www.opengroup.org/</xref>.
Note that some <codeph>argv</codeph> parameters must be used to distinguish
the behaviour of the parent process from the subsequent behaviour of the child
when the <codeph>main()</codeph> function is called; the behaviour of the
child cannot be identical to the parent. </p><p>The subsequent sections provide
the following information: <ul>
<li><p><b>Parent process forking example</b></p></li>
<li><p><b>P.I.P.S. equivalent</b></p></li>
</ul></p></section>
<section><title>Parent process forking example</title><codeblock xml:space="preserve">#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;
}
</codeblock><p/></section>
<section><title>P.I.P.S. equivalent</title><codeblock xml:space="preserve">#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;
}
</codeblock></section>
<section><title>A lot of data passed to child</title><p>The second issue is
where there is too much data to be passed across to the child process using
the <xref href="GUID-E7C4DE71-BC5B-34AE-ACB3-C34A0DB1FC16.dita"><apiname>posix_spawn()</apiname></xref> call. A common work-around used in systems
where <codeph>fork()</codeph> 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 <codeph>fork()</codeph> is that <codeph>fork()</codeph> 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. </p></section>
</conbody></concept>