Example 11-1 illustrates the basic use of the message queue feature. The example uses the posix_spawn() system call and demonstrates how MIPC can be used with a POSIX process.
For more information, refer to the msgSpaceCreate(2K), msgSpaceOpen(2K), msgAllocate(2K), msgPut(2K), msgGet(2K) and msgFree(2K) man pages.
(file: opt/examples/progov/msgSpace.c) #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <chorus.h> #include <mipc/chMipc.h> #include <spawn.h> char* spawn_args[3]; #define NB_MSG_POOLS 2 #define NB_MSG_QUEUES 3 #define SMALL_MSG_SZ 32 #define LARGE_MSG_SZ 256 #define NB_SMALL_MSG 13 #define NB_LARGE_MSG 4 #define SAMPLE_SPACE 1111 #define LARGE_POOL 0 #define SMALL_POOL 1 #define Q1 0 #define Q2 1 #define Q3 2 KnMsgPool samplePools[NB_MSG_POOLS]; char* tagPtr = "Spawned"; int main(int argc, char** argv, char**envp) { int res; int msgSpaceLi; char* smallMsg; char* smallReply; char* largeMsg; KnActorPrivilege actorP; res = actorPrivilege(K_MYACTOR, &actorP, NULL); if (res != K_OK) { printf("Cannot get actor privilege, error %d\n", res); exit(1); } if (argc == 1) { /* * This is the first actor (or spawning actor): * Create a message space, * Spawn another actor, * Allocate, modify and post a small message on Q2 * Get a large Message from Q3, print its contents, free it * Get reply of small message on Q1, print its contents, free it. */ samplePools[LARGE_POOL].msgSize = LARGE_MSG_SZ; samplePools[LARGE_POOL].msgNumber = NB_LARGE_MSG; samplePools[SMALL_POOL].msgSize = SMALL_MSG_SZ; samplePools[SMALL_POOL].msgNumber = NB_SMALL_MSG; msgSpaceLi = msgSpaceCreate(SAMPLE_SPACE, NB_MSG_QUEUES, NB_MSG_POOLS, samplePools); if (msgSpaceLi < 0) { printf("Cannot create the message space error %d\n", msgSpaceLi); exit(1); } /* * Message Space has been created, spawn the other actor, * argv[1] set to "Spawned" to differentiate the 2 actors. */ spawn_args[0] = argv[0]; spawn_args[1] = tagPtr; spawn_args[2] = NULL; res = posix_spawnp(NULL, spawn_args[0], NULL, NULL, spawn_args, NULL); if (res < 0) { printf("Cannot spawn second actor, error %d\n", res); exit(1); } /* * Allocate a small message */ res = msgAllocate(msgSpaceLi, SMALL_POOL, SMALL_MSG_SZ, K_NOTIMEOUT, &smallMsg); if (res != K_OK) { printf("Cannot allocate a small message, error %d\n", res); exit(1); } /* * Initialize the allocated message */ strncpy(smallMsg, "Sending a small message\n", SMALL_MSG_SZ); /* * Post the allocated small message to Q2 with priority 2 */ res = msgPut(msgSpaceLi, Q2, smallMsg, 2); if (res != K_OK) { printf("Cannot post the small message to Q2, error %d\n", res); exit(1); } /* * Get a large message from Q3 and print its contents */ res = msgGet(msgSpaceLi, Q3, K_NOTIMEOUT, &largeMsg, NULL); if (res != K_OK) { printf("Cannot get the large message from Q3, error %d\n", res); exit(1); } printf("Received large message contains:\n%s\n", largeMsg); /* * Free the received large message */ res = msgFree(msgSpaceLi, largeMsg); if (res != K_OK) { printf("Cannot free the large message, error %d\n", res); exit(1); } /* * Get the reply to small message from Q1 and print its contents */ res = msgGet(msgSpaceLi, Q1, K_NOTIMEOUT, &smallReply, NULL); if (res != K_OK) { printf("Cannot get the small message reply from Q1, " "error %d\n", res); exit(1); } printf("Received small reply contains:\n%s\n", smallReply); /* * Free the received small reply */ res = msgFree(msgSpaceLi, smallReply); if (res != K_OK) { printf("Cannot free the small reply message, error %d\n", res); exit(1); } } else { /* * This is the spawned actor: * Check we have effectively been spawned * Open the message space * Allocate, initialize and post a large message to Q3 * Get a small message from Q2, print its contents * Modify it and repost it to Q1 */ int l; if ((argc != 2) || (strcmp(argv[1], tagPtr) != 0)) { printf("%s does not take any argument!\n", argv[0]); exit(1); } /* * Open the message space, using the same global identifier */ msgSpaceLi = msgSpaceOpen(SAMPLE_SPACE); if (msgSpaceLi < 0) { printf("Cannot open the message space error %d\n", msgSpaceLi); exit(1); } /* * Allocate the large message */ res = msgAllocate(msgSpaceLi, K_ANY_MSGPOOL, LARGE_MSG_SZ, K_NOTIMEOUT, &largeMsg); if (res != K_OK) { printf("Cannot allocate a large message, error %d\n", res); exit(1); } strcpy(largeMsg, "Sending a very large large large message\n"); /* * Post the large message to Q3 with priority 0 */ res = msgPut(msgSpaceLi, Q3, largeMsg, 0); if (res != K_OK) { printf("Cannot post the large message to Q3, error %d\n", res); exit(1); } /* * Get the small message from Q2 */ res = msgGet(msgSpaceLi, Q2, K_NOTIMEOUT, &smallMsg, NULL); if (res != K_OK) { printf("Cannot get the small message from Q2, error %d\n", res); exit(1); } printf("Spawned actor received small message containing:\n%s\n", smallMsg); for (l = 0; l < strlen(smallMsg); l++) { if ((smallMsg[l]>= 'a') && (smallMsg[l] <= 'z')) { smallMsg[l] = smallMsg[l] - 'a' + 'A'; } } /* * Post the small message back to Q1, with priority 4 */ res = msgPut(msgSpaceLi, Q1, smallMsg, 4); if (res != K_OK) { printf("Cannot post the small message reply to Q1, error %d\n", res); exit(1); } } return 0; }
Two actors are used, one spawned by the other. The first actor:
Creates a message space with two pools of messages and three message queues (as shown in Figure 11-5).
Allocates a small message, initializes it and posts it to a queue.
Waits for a large message on a second queue, prints its contents and deallocates it.
Waits for the small message to come back on a third queue, prints its contents, deallocates it, then terminates.
During this time, the second actor:
Opens the message space, allocates a large message to be initialized and sends it to the first actor.
Receives the small message, converts all lower case characters to upper case, and posts it back to the third queue before terminating.