Symbian3/PDK/Source/GUID-AA49FB68-22A1-417F-AB57-9C22CE016B21.dita
changeset 1 25a17d01db0c
child 3 46218c8b8afa
equal deleted inserted replaced
0:89d6a7a84779 1:25a17d01db0c
       
     1 <?xml version="1.0" encoding="utf-8"?>
       
     2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
       
     3 <!-- This component and the accompanying materials are made available under the terms of the License 
       
     4 "Eclipse Public License v1.0" which accompanies this distribution, 
       
     5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
       
     6 <!-- Initial Contributors:
       
     7     Nokia Corporation - initial contribution.
       
     8 Contributors: 
       
     9 -->
       
    10 <!DOCTYPE concept
       
    11   PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
       
    12 <concept id="GUID-AA49FB68-22A1-417F-AB57-9C22CE016B21" xml:lang="en"><title>Parent
       
    13 and Child IPC Using a Single Pipe</title><prolog><metadata><keywords/></metadata></prolog><conbody>
       
    14 <p>In this scenario, the parent and child processes communicate using a single
       
    15 pipe. The following pseudo code details the mechanism used by code in the
       
    16 parent process in a Unix-like system. <codeblock xml:space="preserve">//Call pipe() to create the pipe.
       
    17 //Call Fork().
       
    18 if (child process)
       
    19 {
       
    20    //Child Process.
       
    21    //duplicate (via a dup2() call) the read/write end of the pipe using  
       
    22    //prior agreed file descriptor numbers which will subsequently be used by the   //child process following the exec() call.
       
    23    //Close the original file descriptors.
       
    24    //Call exec() to replace the code image in the child process.
       
    25 }
       
    26 else
       
    27 {
       
    28    //Parent process
       
    29    //Do Whatever
       
    30 }
       
    31 </codeblock></p>
       
    32 <p>Instead of using the <codeph>fork()</codeph>/<codeph>exec()</codeph> as
       
    33 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
       
    34 as defined in <filepath>stdio.h</filepath>. Rather than using a pipe for the
       
    35 IPC mechanism the parent process communicates with the child using the stream
       
    36 returned by the <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> call, while the child process input
       
    37 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>
       
    38 <p>However if the parent process requires a file descriptor it can be obtained
       
    39 by using the <xref href="GUID-7A399B7D-553D-345E-92BD-43A8A8224D39.dita"><apiname>fileno()</apiname></xref> API call. For more information about
       
    40 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>
       
    41 <p><b>Parent process <codeph>fork()</codeph> and <codeph>exec()</codeph> functions</b></p>
       
    42 <p>The following code shows the use of a pipe and subsequent <codeph>fork()</codeph>/<codeph>exec()</codeph> calls
       
    43 to create a Pipe for IPC. The example shown is the child process writing data
       
    44 to the pipe, and the parent process receiving the data.</p>
       
    45 <codeblock xml:space="preserve">//Child Process File Descriptors for the pipe. These should be defined in a common header 
       
    46 //file used to compile both the parent and child process's executable.
       
    47 //However #define is here for clarity.
       
    48 #define WRITE_FD  104
       
    49 int main(int argc, char *argv[])
       
    50 {
       
    51   int pipeEnds[2]; //Pipe file descriptors [0] is for read [1] is for write
       
    52   
       
    53   //create the pipe
       
    54   if(pipe(pipeEnds) != 0)
       
    55   {
       
    56      //Pipe creation error
       
    57      return EXIT_FAILURE;
       
    58   }
       
    59   else
       
    60   {
       
    61      pid_t Childpid = fork();
       
    62      
       
    63      if(Childpid == 0)
       
    64      {
       
    65          //close the redundant read FD obtained from the parent process
       
    66          (void)close(pipeEnds[0]);
       
    67     
       
    68          //duplicate the file descriptor for use following exec().
       
    69          if(dup2(pipeEnds[1], WRITE_FD) == -1)
       
    70          {
       
    71             printf("dup2 error\n");
       
    72             return EXIT_FAILURE;
       
    73          }
       
    74          //close the redundant write FD obtained from the parent process
       
    75          (void)close(pipeEnds[1]);
       
    76     
       
    77          //exec() to replace the child process executable
       
    78          char execFileName[] = "/root/PortDoc/Example1_c/Posix/Child/ChildProg";
       
    79          execl(execFileName,NULL);
       
    80       }
       
    81       else
       
    82       {
       
    83          //Parent process. This reads from the pipe. Therefore close the write end of the
       
    84          //pipe.
       
    85          close(pipeEnds[1]);
       
    86     
       
    87          //declare receive buffer, and clear its contents
       
    88          char RxBuffer[100];
       
    89          memset(RxBuffer,0,sizeof(RxBuffer));
       
    90     
       
    91          //Wait for data from the child process. Child sends a string.
       
    92          read(pipeEnds[0],RxBuffer,sizeof(RxBuffer));
       
    93     
       
    94          printf(RxBuffer);
       
    95 
       
    96          //close the Read end of the pipe
       
    97          close(pipeEnds[0]);
       
    98     
       
    99          //Wait for the child process to terminate
       
   100          waitpid(Childpid,NULL,0);
       
   101       }
       
   102    }
       
   103    return EXIT_SUCCESS;
       
   104 }
       
   105 </codeblock>
       
   106 <p><b>Child process created using <codeph>fork()</codeph> or <codeph>exec()</codeph> functions</b></p>
       
   107 <p>The following code shows an example of the child process source which will
       
   108 be executed following the <codeph>exec()</codeph>. </p>
       
   109 <codeblock xml:space="preserve">//Child Process File Descriptors for the pipe. These should be defined in a common header 
       
   110 //file used to compile both the parent and child process's executable. Shown here for
       
   111 //clarity.
       
   112 #define WRITE_FD  104
       
   113 
       
   114 int main(void)
       
   115 {
       
   116    char TxMsg[] = "Hello Parent\n";
       
   117     
       
   118    //Send the message to the parent
       
   119    write(WRITE_FD,TxMsg,sizeof(TxMsg));
       
   120     
       
   121    //close the File Descriptor
       
   122    close(WRITE_FD);
       
   123    return EXIT_SUCCESS;
       
   124 }
       
   125 </codeblock>
       
   126 <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>
       
   127 <p>The following code shows how the above code can be modified to use <codeph>popen()</codeph>,
       
   128 rather than the <codeph>fork()</codeph>/<codeph>exec()</codeph> combination. </p>
       
   129 <codeblock xml:space="preserve">int main(int argc, char *argv[])
       
   130 {
       
   131    //Create child process using popen(). Child process writes to the Parent therefore "r" 
       
   132    //parameter.
       
   133    FILE* ChildProcessStream = popen("/root/PortDoc/Example1_c/Symbian/Child/ChildProg","r");
       
   134           
       
   135    if(ChildProcessStream == NULL)
       
   136    {
       
   137       printf("\n Failure to create child process with popen()\n");
       
   138       return EXIT_FAILURE;
       
   139    }
       
   140    else
       
   141    {
       
   142       //Use a file descriptor rather than a stream
       
   143       int ChildProcessFD = fileno(ChildProcessStream);
       
   144 
       
   145       //Create a receive buffer, and zero contents before receiving.
       
   146       char RxBuffer[100];
       
   147       memset(RxBuffer,0,sizeof(RxBuffer));
       
   148       
       
   149       //Wait for data from the child process. Child sends a string.
       
   150       int nbytes = read(ChildProcessFD,RxBuffer,sizeof(RxBuffer));
       
   151 
       
   152       //printf is slightly different from the POSIX example to verify that the data output to the 
       
   153       //screen is done by the parent process.
       
   154       printf("\n Message Received by Parent=%s",RxBuffer);
       
   155       
       
   156       //Wait for Child Process to complete
       
   157       pclose(ChildProcessStream);
       
   158    }
       
   159    return EXIT_SUCCESS;
       
   160 }
       
   161 </codeblock>
       
   162 <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>
       
   163 <p>The following code shows how the child process source can be modified when
       
   164 it is executed using <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref>. Note that rather
       
   165 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
       
   166 the <codeph>stdout</codeph> streams are directed to the parent process, as
       
   167 defined in the usage of the <xref href="GUID-A9DB6E7C-B8D6-377A-BBE6-39E0A7A09E5D.dita"><apiname>popen()</apiname></xref> call. </p>
       
   168 <codeblock xml:space="preserve">int main(void)
       
   169 {
       
   170     //Child process created by popen() so that its stdout is streamed to the parent process
       
   171     char TxMsg[] = "Hello Parent\n";
       
   172     
       
   173     //Send the message to the parent
       
   174     printf(TxMsg);
       
   175     
       
   176     return EXIT_SUCCESS;
       
   177 }
       
   178 </codeblock>
       
   179 </conbody></concept>