ChorusOS 4.0 Introduction

IPC

IPC is a set of programming interfaces that allow you to create and manage individual program processes that can run concurrently in an operating system. This allows a program to handle many user requests at the same time. Since a single user request may result in multiple processes running in the operating system on the user's behalf, the processes need to communicate with other users. The IPC interfaces make this possible. Each IPC method has its own advantages and limitations so it is not unusual for a single program to use all of the IPC methods. IPC methods include:

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

Refer to the grpAllocate(2K), grpPortInsert(2K), ipcReceive(2K), ipcSend(2K), ipcTarget(2K), portCreate(2K), and portDelete(2K) man pages.


Example 8-3 Communicating Using IPC

(file: progov/ipcSend.c)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <chorus.h>
#include <am/afexec.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       */
static KnCap           clientCap;      /* Capability of the spawned  */
                                       /* actor                      */

/* 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];

/* Parameter for actor spawning */
AcParam param;

/* 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
             */
        stamp = malloc(STAMPSIZE);
        sprintf(stamp, "%d", MYSTAMP);

        rslt = afexeclp(argv[0], &clientCap, NULL , argv[0], stamp, NULL);
        if (rslt == -1) {                                             
            printf("Cannot spawn client actor, error %d\n", errno);   
            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;
}