COHERENT manpages

This page displays the COHERENT manpage for msgget() [Create or get a message queue].

List of available manpages
Index


msgget() -- General Function (libc)

Create or get a message queue
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
msgget(key, flag)
key_t key; int flag;

The function  msgget() gets or  creates a message queue.   If necessary, it
can create a message queue and  its control structure, and link them to the
identifier key.

key  is  an identifier  that  your application  generates  to identify  its
message queues.  To  guarantee that each key is unique,  you should use the
function call ftok() to generate keys.

When it creates a message queue,  msgget() also creates a copy of structure
msqid_ds, which the header file <sys/msg.h> defines as follows:

struct msqid_ds {
     struct ipc_perm msg_perm;/* operation permission struct */
     struct msg *msg_first; /* ptr to first message on queue */
     struct msg *msg_last;  /* ptr to last message on queue */
     unsigned short msg_cbytes;/* current # bytes on queue */
     unsigned short msg_qnum;/* # of messages on queue */
     unsigned short msg_qbytes;/* max # of bytes on queue */
     unsigned short msg_lspid;/* pid of last msgsnd() */
     unsigned short msg_lrpid;/* pid of last msgrcv() */
     time_t msg_stime;      /* last msgsnd() time */
     time_t msg_rtime;      /* last msgrcv() time */
     time_t msg_ctime;      /* last change() time */
};

The messages themselves consist of a linked list of structures of type msg.
Fields msg_first  and msg_last point  to, respectively, the  first and last
messages in the  list.  Header file <sys/msg.h> defines structure msg
as follows:

struct msg {
     struct msg *msg_next;  /* pointer to next message on queue */
     long msg_type;         /* message type */
     short msg_ts;          /* message text size */
     short msg_spot;        /* message text map address */
};

Field  msg_perm  is  a  structure  of  type  ipc_perm,  which  header  file
<sys/ipc.h> defines as follows:

struct ipc_perm {
     unsigned short uid;    /* owner's user id */
     unsigned short gid;    /* owner's group id */
     unsigned short cuid;   /* creator's user id */
     unsigned short cgid;   /* creator's group id */
     unsigned short mode;   /* access modes */
     unsigned short seq;    /* slot usage sequence number */
     key_t key;             /* key */
};

msgget() initializes msqid_ds as follows:

-> It  sets  the  fields  msg_perm.cuid, msg_perm.uid,  msg_perm.cgid,  and
   msg_perm.gid to, respectively, the effective user ID and effective group
   ID of the calling process.

-> It sets  the low-order nine bits of msg_perm.mode  to the low-order nine
   bits of  flag. These nine bits define access  permissions: the top three
   bits  give the  owner's access permissions  (read, write,  execute), the
   middle three  bits the  owning group's  access permissions, and  the low
   three bits access permissions for others.

-> It sets msg_ctime is set to the current time.

-> It sets msg_qbytes to the value of kernel variable NMSQB, which sets the
   maximum number of bytes available to the message queue.

If any of  the following error conditions is true,  msgget() returns -1 and
sets errno to the value within parentheses:

-> key  already has  a message  queue, but  the owner  of the  process that
   called msgget() does not have permission to read it (EACCES).

-> key does not  have a message queue associated with  it, but flag is does
   not request  that one be  created (i.e., flag &amp;  IPC_CREAT is false)
   (ENOENT).

-> flag requests  that msgget()  create a  message queue, but  the system's
   maximum number of message queues  (as set by the kernel variable NMSQID)
   already exists (ENOSPC).

-> key  already has  a message  queue, but  flag requests  that a  queue be
   created exclusively (i.e., (flag &amp; IPC_CREAT) &amp;&amp; (flag &amp;
   IPC_EXCL) is true) (EEXIST).

If all  goes well msgget()  returns the message-queue  identifier, which is
always a non-negative integer.  Otherwise,  it returns -1 and sets errno to
an appropriate value.

Example

The  following  program,  samplemsg.c, gives  an  example  of the  COHERENT
message  facility.  One  server process  accepts  user keyboard  input, and
sends it  client 1 if  the first character  is an upper-case  letter, or to
client 2 if the first character is not an upper-case letter.

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/wait.h>

/* Maximum size of messages in this example.
 * The default maximum size is 2048. */
#define MAX_MSG_SIZE 80

/* template for a message */
struct my_msg {
    long mtype;
    unsigned char mtext[MAX_MSG_SIZE];
};

struct my_msg sndmsg; /* message we will send */
struct my_msg rcvmsg; /* message we will receive */

key_t key;     /* key for getting our message queue */
int id;        /* message queue id returned by msgget() */
long msgtype;  /* type of the message */

main()
{
               /* Generate unigue key */
               if ((key = ftok("./samplemsg", 'A')) == -1)
               fprint (stderr, "samplemsg does not exist.\n");
               exit(EXIT_FAILURE);
               }

               /* get our message queue, abort on error */
               if( -1 == (id = msgget(key, IPC_CREAT|0660))){
               printf("Error obtaining message queue\n");
               exit(EXIT_FAILURE);
               }

               printf("To end this demonstration, type 'end'.\n"
               "Enter the message -> ");
               fflush(stdout);
               msgtype = 1;/* 1st client receives messages of type 1 */

               /* fork() to produce our 1st client processes. */
               if (fork()) { /* we are parent process (server) */
               msgtype = 2; /* 2nd client receives messages of type 2 */
               /* fork() again to produce our 2nd client processes. */
               if (fork()) { /* we are parent process (server) */
                send_messages(); /* server */
               } else
                receive_messages(); /* second client */
               } else
               receive_messages(); /* 1st client */
               exit (EXIT_SUCCESS);
}

/* Get a message from user and send it to client or child processes */
send_messages()
{
               for (;;) {
               /* get our message to send */
               gets(sndmsg.mtext);

               /* if 'end' was entered, send message to BOTH clients,
                * as this is a flag for them to terminate themselves.
                * Otherwise, just send the message.
                */
               if (!strcmp(sndmsg.mtext,"end")) {
                sndmsg.mtype = 1;
                msgsnd(id, &sndmsg, strlen(sndmsg.mtext)+1, 0);
                sndmsg.mtype = 2;
                msgsnd(id, &sndmsg, strlen(sndmsg.mtext)+1, 0);
                printf("Thank you. Bye.\n");
                break;
               }

               /* Determine the type of message this will be.
                * if the first character is upper case letter,
                * then this is a type-1 message; otherwise,
                * this is a type-2 message.
                */
               if (isupper(sndmsg.mtext[0]))
                sndmsg.mtype = 1L;
               else
                sndmsg.mtype = 2L;

               if (msgsnd(id, &sndmsg, strlen(sndmsg.mtext)+1, 0) < 0) {
                perror("send");
                break;
               }
               }

               while (wait(NULL) > 0)/* Wait for the children */
               ;
               msgctl(id, IPC_RMID,0); /* remove message queue */
               return;
}

/* receive_messages(). */
receive_messages()
{
               char clntbuf[20];

               sprintf(clntbuf, "Client %ld", msgtype);

               for (;;) {
               if (msgrcv(id, &rcvmsg, MAX_MSG_SIZE, msgtype, 0) < 0) {
                perror(clntbuf);
                exit(EXIT_FAILURE);
               }

               printf("%s received: '%s'\n", clntbuf, rcvmsg.mtext);
               if (!strcmp(rcvmsg.mtext,"end"))
                break;
               printf("Enter next message -> ");
               fflush(stdout);
               }
               exit(EXIT_SUCCESS);
}

Files

/usr/include/sys/ipc.h
/usr/include/sys/msg.h

See Also

ftok(),
ipcrm,
ipcs,
libc,
libsocket,
msgctl(),
msgrcv(),
msgsnd()

Notes

Prior to  release 4.2, COHERENT  implemented semaphores through  the driver
msg.  In release  4.2, and  subsequent  releases, COHERENT  has implemented
semaphores as  a set of  functions that conform  in large part  to the UNIX
System-V standard.