Week 23 contribution of PDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.
<?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-AA49FB68-22A1-417F-AB57-9C22CE016B21" xml:lang="en"><title>Parent
and Child IPC Using a Single Pipe</title><prolog><metadata><keywords/></metadata></prolog><conbody>
<p>In this scenario, the parent and child processes communicate using a single
pipe. The following pseudo code details the mechanism used by code in the
parent process in a Unix-like system. <codeblock xml:space="preserve">//Call pipe() to create the pipe.
//Call Fork().
if (child process)
{
//Child Process.
//duplicate (via a dup2() call) the read/write end of the pipe using
//prior agreed file descriptor numbers which will subsequently be used by the //child process following the exec() call.
//Close the original file descriptors.
//Call exec() to replace the code image in the child process.
}
else
{
//Parent process
//Do Whatever
}
</codeblock></p>
<p>Instead of using the <codeph>fork()</codeph>/<codeph>exec()</codeph> as
described above, POSIX libraries including P.I.P.S. provide the <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> function
as defined in <filepath>stdio.h</filepath>. Rather than using a pipe for the
IPC mechanism the parent process communicates with the child using the stream
returned by the <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> call, while the child process input
or output is using the <xref href="GUID-C0C1D22B-298F-3E8D-A1E9-6F5EFA81F9E8.dita"><apiname>stdin()</apiname></xref>/<xref href="GUID-85797574-E2A2-3C0C-9670-C178078DE199.dita"><apiname>stdout()</apiname></xref> streams. </p>
<p>However if the parent process requires a file descriptor it can be obtained
by using the <xref href="GUID-7A399B7D-553D-345E-92BD-43A8A8224D39.dita"><apiname>fileno()</apiname></xref> API call. For more information about
the <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> function, see <xref href="http://www.opengroup.org" scope="external">http:\\www.opengroup.org</xref>. </p>
<p><b>Parent process <codeph>fork()</codeph> and <codeph>exec()</codeph> functions</b></p>
<p>The following code shows the use of a pipe and subsequent <codeph>fork()</codeph>/<codeph>exec()</codeph> calls
to create a Pipe for IPC. The example shown is the child process writing data
to the pipe, and the parent process receiving the data.</p>
<codeblock xml:space="preserve">//Child Process File Descriptors for the pipe. These should be defined in a common header
//file used to compile both the parent and child process's executable.
//However #define is here for clarity.
#define WRITE_FD 104
int main(int argc, char *argv[])
{
int pipeEnds[2]; //Pipe file descriptors [0] is for read [1] is for write
//create the pipe
if(pipe(pipeEnds) != 0)
{
//Pipe creation error
return EXIT_FAILURE;
}
else
{
pid_t Childpid = fork();
if(Childpid == 0)
{
//close the redundant read FD obtained from the parent process
(void)close(pipeEnds[0]);
//duplicate the file descriptor for use following exec().
if(dup2(pipeEnds[1], WRITE_FD) == -1)
{
printf("dup2 error\n");
return EXIT_FAILURE;
}
//close the redundant write FD obtained from the parent process
(void)close(pipeEnds[1]);
//exec() to replace the child process executable
char execFileName[] = "/root/PortDoc/Example1_c/Posix/Child/ChildProg";
execl(execFileName,NULL);
}
else
{
//Parent process. This reads from the pipe. Therefore close the write end of the
//pipe.
close(pipeEnds[1]);
//declare receive buffer, and clear its contents
char RxBuffer[100];
memset(RxBuffer,0,sizeof(RxBuffer));
//Wait for data from the child process. Child sends a string.
read(pipeEnds[0],RxBuffer,sizeof(RxBuffer));
printf(RxBuffer);
//close the Read end of the pipe
close(pipeEnds[0]);
//Wait for the child process to terminate
waitpid(Childpid,NULL,0);
}
}
return EXIT_SUCCESS;
}
</codeblock>
<p><b>Child process created using <codeph>fork()</codeph> or <codeph>exec()</codeph> functions</b></p>
<p>The following code shows an example of the child process source which will
be executed following the <codeph>exec()</codeph>. </p>
<codeblock xml:space="preserve">//Child Process File Descriptors for the pipe. These should be defined in a common header
//file used to compile both the parent and child process's executable. Shown here for
//clarity.
#define WRITE_FD 104
int main(void)
{
char TxMsg[] = "Hello Parent\n";
//Send the message to the parent
write(WRITE_FD,TxMsg,sizeof(TxMsg));
//close the File Descriptor
close(WRITE_FD);
return EXIT_SUCCESS;
}
</codeblock>
<p><b>Parent process P.I.P.S. example for <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> function</b></p>
<p>The following code shows how the above code can be modified to use <codeph>popen()</codeph>,
rather than the <codeph>fork()</codeph>/<codeph>exec()</codeph> combination. </p>
<codeblock xml:space="preserve">int main(int argc, char *argv[])
{
//Create child process using popen(). Child process writes to the Parent therefore "r"
//parameter.
FILE* ChildProcessStream = popen("/root/PortDoc/Example1_c/Symbian/Child/ChildProg","r");
if(ChildProcessStream == NULL)
{
printf("\n Failure to create child process with popen()\n");
return EXIT_FAILURE;
}
else
{
//Use a file descriptor rather than a stream
int ChildProcessFD = fileno(ChildProcessStream);
//Create a receive buffer, and zero contents before receiving.
char RxBuffer[100];
memset(RxBuffer,0,sizeof(RxBuffer));
//Wait for data from the child process. Child sends a string.
int nbytes = read(ChildProcessFD,RxBuffer,sizeof(RxBuffer));
//printf is slightly different from the POSIX example to verify that the data output to the
//screen is done by the parent process.
printf("\n Message Received by Parent=%s",RxBuffer);
//Wait for Child Process to complete
pclose(ChildProcessStream);
}
return EXIT_SUCCESS;
}
</codeblock>
<p><b>Child process P.I.P.S. example for <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> function</b></p>
<p>The following code shows how the child process source can be modified when
it is executed using <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref>. Note that rather
than using a file descriptor for the communication via the pipe the <xref href="GUID-C0C1D22B-298F-3E8D-A1E9-6F5EFA81F9E8.dita"><apiname>stdin()</apiname></xref> or
the <codeph>stdout</codeph> streams are directed to the parent process, as
defined in the usage of the <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> call. </p>
<codeblock xml:space="preserve">int main(void)
{
//Child process created by popen() so that its stdout is streamed to the parent process
char TxMsg[] = "Hello Parent\n";
//Send the message to the parent
printf(TxMsg);
return EXIT_SUCCESS;
}
</codeblock>
</conbody></concept>