Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


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:

This example is located in the examples\PIPS\IPC folder. The following sections provide more information about this example application.

[Top]


Description


Spawning the child process

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.


Creating a named pipe

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.


Opening a single pipe

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.

[Top]


Build

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

[Top]


Runtime setting

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.

[Top]


Example code


bld.inf

// BLD.INF
//
// Copyright (c) 2007 Symbian Software Ltd.  All rights reserved.
//
PRJ_MMPFILES

ipcparent.mmp
ipcchild.mmp
fifochild.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

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

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

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

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

// 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;
    }