ChorusOS 5.0 Application Developer's Guide

Using IPC

The following example illustrates the use of the IPC mechanisms provided in the ChorusOS operating system.


Example 11-2 Communicating Using IPC

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <chorus.h>
#include <spawn.h>
#include "ipc/chIpc.h"

#define ABORT_DELAY 1000             /* Delay for ipcReceive       */

static KnUniqueId      thePortUi;    /* Our port unique identifier */
static int             thePortLi;    /* .......  local identifier  */
static KnCap           groupCap;     /* Our group capability       */

/* The outgoing annex and body  */
static char sndAnnex[] = "Hello world from Chorus ...\n";
static char sndBody[]  = "The sea is calm, the tide is full ...\n";

/* The received annex and body  */
static char rcvAnnex[K_CMSGANNEXSIZE];
static char rcvBody[1000];

/* Argumentf for the spawnd process */
static char* spawn_args[3];

/* Port group stamp             */
char*       stamp;
#define MYSTAMP   100
#define STAMPSIZE  10

int main(int argc, char** argv, char** envp)
{
    int         rslt;        /* Work */
    KnMsgDesc   smsg;        /* Descriptor for message being sent */
    KnMsgDesc   rmsg;        /* Descriptor for message being received */
    KnIpcDest   ipcDest;     /* IPC address */

    if (argc == 1) {
            /* 
             * Server actor
             * Create the destination port
             */
        thePortLi = portCreate(K_MYACTOR, &thePortUi);
        if (thePortLi < 0) {                                      
            printf("portCreate failed, returns %d\n", thePortLi); 
            exit(1);                                              
        }                                                         
            /*
             * Allocate a port group and insert the port into it
             */
        rslt = grpAllocate(K_STATUSER, &groupCap, MYSTAMP);
        if (rslt < 0) {                                           
            printf("grpAllocate failed, returns %d\n", rslt);     
            exit(1);                                              
        }                                                         
   
        rslt = grpPortInsert(&groupCap, &thePortUi);
        if (rslt < 0) {                                           
            printf("grpPortInsert failed, returns %d\n", rslt);   
            exit(1);                                              
        }
            /*
             * Spawn the client actor
             * The group stamp is given in argument
					 * Exit in case of malloc failure
             */
        stamp = malloc(STAMPSIZE);
			  if (stamp == NULL) {
					printf("Can't allocate %d bytes\n", STAMPSIZE);
					exit(1);
			  }
        sprintf(stamp, "%d", MYSTAMP);
        
        spawn_args[0] = argv[0];
        spawn_args[1] = stamp;
        spawn_args[2] = NULL;

        rslt = posix_spawnp(NULL, spawn_args[0], NULL, 
	       NULL, spawn_args, NULL);
        if (rslt < 0) {                                             
            printf("Cannot spawn client actor, error %d\n", rslt);  
            exit(1);                                                
        }                                                           
            /*
             * Receive the message
             */
        rmsg.flags     = 0;
        rmsg.bodySize  = sizeof(rcvBody);
        rmsg.bodyAddr  = (VmAddr)rcvBody;
        rmsg.annexAddr = (VmAddr)rcvAnnex;

        rslt = ipcReceive(&rmsg, &thePortLi, ABORT_DELAY);
        if (rslt < 0) {                                             
            printf("ipcReceive failed, returns %d\n", rslt);        
            exit(1);                                                
        }                                                           

        printf ("%s\n%s\n", rcvAnnex, rcvBody);
    
        rslt = portDelete(K_MYACTOR, thePortLi);
        if (rslt < 0) {                                               
            printf("portDelete failed, returns %d\n", rslt);          
            exit(1);                                                  
        }                                                             
    } else {
            /*
             * Get the port group capability giving the stamp.
             * Stamp has been received in argv[1]
             */
        rslt = grpAllocate(K_STATUSER, &groupCap, (int) atoi(argv[1]));
        if (rslt < 0) {                                               
            printf("grpAllocate failed, returns %d\n", rslt);         
            exit(1);                                                  
        }                                                             
            /*
             * Prepare the message descriptor for the message to send
             */
        smsg.flags     = 0;
        smsg.bodySize  = sizeof(sndBody);
        smsg.bodyAddr  = (VmAddr)sndBody;
        smsg.annexAddr = (VmAddr)sndAnnex;
            /* 
             * Prepare the IPC address for the message destination.
             * Send the message in broadcast mode.
             */
        ipcDest.target = groupCap.ui;
        rslt = ipcTarget(&ipcDest.target, K_BROADMODE);
        if (rslt < 0) {                                               
            printf("ipcTarget failed, returns %d\n", rslt);           
            exit(1);                                                  
        }                                                             

            /* Send from our DEFAULT port */
        rslt = ipcSend(&smsg, K_DEFAULTPORT, &ipcDest);
        if (rslt < 0) {                                               
            printf("ipcSend failed, returns %d\n", rslt);             
            exit(1);                                                  
        }                                                             
    }

    return 0;
}

In this example, the main thread (which is implicitly created):

The spawned actor: