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 & 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 & IPC_CREAT) && (flag & 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.