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