Symbian3/SDK/Source/GUID-AA49FB68-22A1-417F-AB57-9C22CE016B21.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.

<?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>