The following code example shows how to share memory between applications.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <chorus.h>
#include <cx/afexec.h>
AcParam param;
#define RGN_SIZE (3 * vmPageSize())
#define SHARED_RGN_SIZE (1 * vmPageSize())
typedef struct sampleSharedArea {
KnSem sem;
char data[1];
} sharea_t;
char capString[80];
char sharedAddr[20];
int main(int argc, char** argv, char**envp)
{
KnRgnDesc rgnDesc;
sharea_t* ptr;
KnCap spawningCap;
KnCap spawnedCap;
int res;
VmFlags rgnOpt = 0;
KnActorPrivilege actorP;
res = actorPrivilege(K_MYACTOR, &actorP, NULL);
if (res != K_OK) {
printf("Cannot get privilege, error %d\n", res);
exit(1);
}
if (actorP == K_SUPACTOR) {
rgnOpt = K_SUPERVISOR;
}
if (argc == 1) {
/*
* This is the first actor (or spawning actor):
* Allocate a memory region
* Initialize a semaphore within the region
* Spawn the second actor
* Wait on the semaphore
* Get data written in shared mem by spawned actor
* Terminate
*/
rgnDesc.size = RGN_SIZE;
rgnDesc.options = rgnOpt | K_ANYWHERE | K_WRITABLE | K_FILLZERO;
rgnDesc.opaque1 = NULL;
rgnDesc.opaque2 = NULL;
res = rgnAllocate(K_MYACTOR, &rgnDesc);
if (res != K_OK) {
printf("Cannot allocate memory, error %d\n", res);
exit(1);
}
ptr = (sharea_t*) rgnDesc.startAddr;
strcpy(&ptr->data[0], "First actor initializing the shared mem\n");
res = semInit(&ptr->sem, 0);
/*
* Get my own capability and pass it as a string argument
* to spawned actor, so that it may use it to share memory
*/
(void) actorSelf(&spawningCap);
sprintf(capString, "0x%x 0x%x 0x%x 0x%x", spawningCap.ui.uiHead,
spawningCap.ui.uiTail, spawningCap.key.keyHead,
spawningCap.key.keyTail);
/*
* Pass address of memory to be shared as a string argument
* to spawned actor.
*/
sprintf(sharedAddr, "0x%x", ptr);
param.acFlags = (actorP == K_SUPACTOR)? AFX_SUPERVISOR_SPACE :
AFX_USER_SPACE;
res = afexeclp(argv[0], &spawnedCap, ¶m , argv[0], capString,
sharedAddr, NULL);
if (res == -1) {
printf("cannot spawn second actor, error %d\n", errno);
exit(1);
}
(void) semP(&ptr->sem, K_NOTIMEOUT);
printf("%s", &ptr->data[0]);
} else {
KnRgnDesc srcRgn;
KnRgnDesc tgtRgn;
unsigned long uHead, uTail, kHead, kTail;
/*
* This is the spawned actor:
* Get arguments
* Set up the memory sharing
* Write some string in shared memory
* Wake up spawning actor
* Terminate
*/
sscanf(argv[1], "0x%x 0x%x 0x%x 0x%x", &uHead, &uTail, &kHead, &kTail);
spawningCap.ui.uiHead = uHead;
spawningCap.ui.uiTail = uTail;
spawningCap.key.keyHead = kHead;
spawningCap.key.keyTail = kTail;
sscanf(argv[2], "0x%x", &srcRgn.startAddr);
if (actorP != K_SUPACTOR) {
srcRgn.size = SHARED_RGN_SIZE;
tgtRgn.startAddr = srcRgn.startAddr;
tgtRgn.size = SHARED_RGN_SIZE;
tgtRgn.options = rgnOpt | K_WRITABLE;
tgtRgn.opaque1 = NULL;
tgtRgn.opaque2 = NULL;
res = rgnMapFromActor(K_MYACTOR, &tgtRgn, &spawningCap, &srcRgn);
if (res != K_OK) {
printf("Cannot share memory, error %d\n", res);
exit(1);
}
ptr = (sharea_t*) tgtRgn.startAddr;
} else {
/*
* Both actors are running in supervisor space,
* There is no need to perform the rgnMapFromActor.
* One may use the received shared address.
*/
ptr = (sharea_t*) srcRgn.startAddr;
}
/* Get data from spawning actor */
printf("Spawning actor sent: %s", &ptr->data[0]);
/* Modify contents of shared memory */
sprintf(&ptr->data[0], "Spawned actor mapped shared memory at 0x%x\n",
ptr);
res = semV(&ptr->sem);
if (res != K_OK) {
printf("Spawned actor failed on semV, error %d\n", res);
exit(1);
}
}
return 0;
}