|
||
IPC
: IPC Mechanisms
This example demonstrates how a parent process communicates with its
child process using various IPC mechanisms. Two executables, a parent and a
child (spawned by the parent) are created to demonstrate these mechanisms. The
child process is created by the parent using the
posix_spawn()
function. The parent process communicates
with the child process using the following IPC mechanisms:
Named pipes (FIFO - First in First Out)
Single pipe (popen()
system call)
This example is located in the examples\PIPS\IPC
folder. The
following sections provide more information about this example application.
The posix_spawn()
function creates the child
process. A pointer to the process ID (pid
) of the child process
and the path of the child process are passed as arguments to this function. The
parent waits for the child to terminate by calling the
waitpid()
function.
This example creates a named pipe using the
mkfifo()
function. The child writes data into the FIFO and
then exits. The parent reads data from FIFO and writes it to the console. The
first argument of the mkfifo()
function indicates the path
of the FIFO file.
The parent creates a child process and a pipe to the child process
using the popen()
function. A file handle to the pipe is
returned to the parent and the parent uses this handle to read the data written
to the pipe by the child. The path of the child process is passed as the first
argument to the popen()
function.
The following statements are present in all the .mmp
files
of the example:
SYSTEMINCLUDE epoc32\include\stdapis
LIBRARY libc.lib
STATICLIBRARY libcrt0.lib
Note: You require these statements because of the following reasons:
The epoc32\include\stdapis
directory contains header
files such as, stdio.h
, unistd.h
and so on that are
required to build an Open Environment application.
The libc.lib
file contains the definitions of all
functions that are defined in the header files associated with this example.
The libcrt0.lib
file provides the
E32Main()
function, which is the entry point for the
main()
function of the example.
The Symbian OS build process describes how to build this example. The IPC
builds
the following binaries in the standard location
(\epoc32\release\winscw\<build_variant>
for Carbide).
ipcparent.exe: Executable of the parent process.
ipcchild.exe: Executable of the child process created
using the popen()
function.
fifochild.exe: Executable of the child process created
using the posix_spawn()
function.
Two eshells must be opened before executing this example. The
executable, ipcparent.exe
is run in one eshell and the other
eshell is used to run the child process fifochild.exe
. You can
switch between the two eshells by pressing
CTRL+ALT+SHIFT+T.
// BLD.INF
//
// Copyright (c) 2007 Symbian Software Ltd. All rights reserved.
//
PRJ_MMPFILES
ipcparent.mmp
ipcchild.mmp
fifochild.mmp
// FIFOCHILD.MMP
//
// Copyright (c) 2007 Symbian Ltd. All rights reserved.
//
TARGET fifochild.exe
TARGETTYPE exe
UID 0xE80000CC
VENDORID 0x70000001
SOURCEPATH ..\src\child
SOURCE fifochild.c
SYSTEMINCLUDE \epoc32\include\stdapis
SYSTEMINCLUDE \epoc32\include
LIBRARY libc.lib euser.lib efsrv.lib
STATICLIBRARY libcrt0.lib
// IPCCHILD.MMP
//
// Copyright (c) 2007 Symbian Ltd. All rights reserved.
//
TARGET ipcchild.exe
TARGETTYPE exe
UID 0xE80000CB
VENDORID 0x70000001
SOURCEPATH ..\src\child
SOURCE ipcchild.c
SYSTEMINCLUDE \epoc32\include\stdapis
SYSTEMINCLUDE \epoc32\include
LIBRARY libc.lib euser.lib efsrv.lib
STATICLIBRARY libcrt0.lib
// IPCPARENT.MMP
//
// Copyright (c) 2007 Symbian Ltd. All rights reserved.
//
TARGET ipcparent.exe
TARGETTYPE exe
UID 0xE80000CA
VENDORID 0x70000001
SOURCEPATH ..\src\parent
SOURCE ipcparent.c
SYSTEMINCLUDE \epoc32\include\stdapis
SYSTEMINCLUDE \epoc32\include
LIBRARY libc.lib euser.lib efsrv.lib
STATICLIBRARY libcrt0.lib
// fifochild.c
//
// Copyright (c) Symbian Software Ltd 2007. All rights reserved.
//
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
/**
Waits for a key press
@return Character code of the key pressed
*/
char PressKey()
{
char ch;
fflush(stdout);
ch=getchar();
return ch;
}
/**
Reports any error with error number from error.h
@param msg Error message to be printed
@return The failure code
*/
int Error(char msg[])
{
printf("%s [Error NUMBER = %d]\n",msg,errno);
PressKey();
return EXIT_FAILURE;
}
int main(int argc, char *argv[])
{
/** Name of the FIFO file to be created*/
char fifoFileName[] = "myfifofile";
/** Open the FIFO file, child process writes data to this file
and the parent process reads data from this file*/
int fifoFd = open(fifoFileName,O_WRONLY);
/** open() returns -1 on failure*/
if(fifoFd == -1)
{
/** Failed to open the FIFO*/
Error("\n*** child failure FIFO Open ***\n");
return EXIT_FAILURE;
}
else
{
/** Create a message to send to the parent*/
char TxMsg[] = "Hello Parent [FIFO]\n";
/** Child process sends a message string to the parent*/
write(fifoFd,TxMsg,sizeof(TxMsg));
/** Close the FIFO*/
(void)close(fifoFd);
}
return EXIT_SUCCESS;
}
// ipcchild.c
//
// Copyright (c) Symbian Software Ltd 2007. All rights reserved.
//
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char msg[]="\r\n*** Child Running ***\r\n";
/** Sleep for 5 seconds*/
sleep(5);
printf(msg);
return EXIT_SUCCESS;
}
// ipcparent.c
//
// Copyright (c) Symbian Software Ltd 2007. All rights reserved.
//
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
/**
Waits for a key press
@return Character code of the key pressed
*/
char PressKey()
{
char ch;
fflush(stdout);
ch=getchar();
return ch;
}
/**
Reports any error with the error number from error.h
@param msg Error message to be printed
@return The failure code
*/
int Error(char msg[])
{
/** Print the error message with the global error number*/
printf("%s [Error NUMBER = %d]\n",msg,errno);
PressKey();
return EXIT_FAILURE;
}
int main(int argc, char *argv[])
{
/** File stream for the pipe opened using popen()*/
FILE* childProcessStream;
/** Name of the FIFO file to be created*/
char fifoFileName[] = "myfifofile";
/** Child process path for FIFO*/
char fifoExecFileName[] = "z:/child/fifochild";
/** Child process path for popen()*/
char popenExecFileName[] = "z:/child/ipcchild";
/** Process ID of child process for FIFO*/
pid_t fifoChildPid;
/** Variables for storing return values of POSIX APIs*/
int fifoRetVal;
int unlinkResult;
int fifoResult;
/** File descriptor of stream opened by popen()*/
int childProcessFD;
/** Create the FIFO file with execute permission to the group. However,
this flag would not have any effect as the concept of a 'process group'
does not exist in Symbian OS Process Model*/
fifoResult = mkfifo(fifoFileName,S_IXGRP);
/** mkfifo() returns -1 in case of an error*/
if(fifoResult == -1)
{
Error("*** failure mkfifo ***");
PressKey();
return EXIT_FAILURE;
}
/** FIFO creation is successful, spawn the child process.*/
fifoRetVal= posix_spawn(&fifoChildPid,fifoExecFileName,NULL,NULL,NULL,NULL);
/** posix_spawn() returns a non-zero integer in case of an error*/
if(fifoRetVal != 0)
{
Error("*** failure posix_spawn ***");
PressKey();
return EXIT_FAILURE;
}
else
{
/** Open the FIFO file, parent reads data from this file*/
int fifoFd = open(fifoFileName,O_RDONLY);
/** open() returns -1 on failure*/
if(fifoFd == -1)
{
/** Failed to open the FIFO*/
Error("*** failure FIFO Open ***");
PressKey();
return EXIT_FAILURE;
}
else
{
/** Create a receive buffer and clear the buffer*/
char buffer[100];
int nbytes;
memset(buffer,0,sizeof(buffer));
/** Wait for data from the child process. Child process sends a string to the parent*/
nbytes = read(fifoFd,buffer,sizeof(buffer));
printf("\nMessage Received by Parent[FIFO]=%s",buffer);
/** Close the FIFO*/
(void)close(fifoFd);
}
/** Create another child process using popen()*/
childProcessStream = popen(popenExecFileName,"r");
/** popen() returns Null if the pipe can not be created*/
if(childProcessStream == NULL)
{
Error("\n Failure to create child process with popen()");
PressKey();
return EXIT_FAILURE;
}
else
{
/** Create a receive buffer and clear its contents before receiving any data from the child process*/
char buffer[100];
/** Number of bytes to be read from the pipe*/
int nbytes;
/** Use a file descriptor rather than a file stream*/
childProcessFD = fileno(childProcessStream);
memset(buffer,0,sizeof(buffer));
printf("\n\nWaiting for message from Child[popen()]\n");
/** Wait for data from the child process. Child process sends a string*/
nbytes = read(childProcessFD,buffer,sizeof(buffer));
printf("Message Received by Parent[popen()]=%s\n[ok]\n",buffer);
/** Close the pipe*/
pclose(childProcessStream);
}
/** Wait for the child process to finish its execution*/
(void)waitpid(fifoChildPid,NULL,0);
/** Delete the FIFO*/
unlinkResult=unlink(fifoFileName);
if(unlinkResult!=0)
{
Error("Unlink error");
}
}
PressKey();
return EXIT_SUCCESS;
}