IPC programming :message queues

http://hi.baidu.com/j%5Ffo/blog/item/95f3f424c721aa328744f9b0.html

/ Message queue control operation. /
int msgctl (int msqid, int cmd, struct msqid_ds __buf);

/
Get messages queue. /
int msgget (key_t key, int msgflg);

/
Receive message from message queue. /
int msgrcv (int __msqid, void
msgp, size_t msgsz, long int msgtyp, int msgflg);

/ Send message to message queue. /
int msgsnd (int msqid, const void msgp, size_t msgsz, int __msgflg);


ipcs
       -t     time
       -p     pid
       -c     creator
       -l     limits
       -u     summary
       -i      id

ipcrm
       -M shmkey
              removes the shared memory segment created with shmkey after the
              last detach is performed.
       -m shmid
              removes the shared memory segment identified by shmid after the
              last detach is performed.
       -Q msgkey
              removes the message queue created with msgkey.
       -q msgid
              removes the message queue identified by msgid.
       -S semkey
              removes the semaphore created with semkey.
       -s semid
              removes the semaphore identified by semid.





/

private-queue-hello-world.c - a "hello world" example in which a single
process creates a message queue and sends
itself a "hello world" message via this queue.
/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int main(int argc, char argv[])
{
    /

    Creating A Message Queue - msgget()
    In order to use a message queue, it has to be created first. The msgget() system call is used to do just that. This system call accepts two parameters - a queue key, and flags. The key may be one of:
        1. IPC_PRIVATE (0) - used to create a private message queue.
        2. a positive integer - used to create (or access) a publicly-accessible message queue.
    The second parameter contains flags that control how the system call is to be processed. It may contain flags like IPC_CREAT or IPC_EXCL, which behave similar to O_CREAT and O_EXCL in the open() system call.
    /
   /
create a private message queue, with access only to the owner. /
   int queue_id = msgget(IPC_PRIVATE, 0600);

    /

    struct msgbuf {
        long mtype; / message type, a positive number (cannot be zero). /
        char mtext[1]; / message body array. usually larger then one byte. /
    };
    /
    struct msgbuf
msg;
   struct msgbuf recv_msg;
   int rc;
   if (queue_id == -1) {
       perror("main: msgget");
       exit(1);
   }
   printf("message queue created, queue id ‘%d’.n", queue_id);
   msg = (struct msgbuf
)malloc(sizeof(struct msgbuf)+strlen("hello world"));

    / set the message type. for example - set it to ‘1’. /
   msg->mtype = 1;
   strcpy(msg->mtext, "hello world");
    /
    Writing Messages Onto A Queue - msgsnd()
    Once we created the message queue, and a message structure, we can place it on the message queue, using the
    msgsnd() system call. This system call copies our message structure and places that as the last message on the queue.
    It takes the following parameters:
        1. int msqid - id of message queue, as returned from the msgget() call.
        2. struct msgbuf
msg - a pointer to a properly initializes message structure, such as the one we prepared in
            the previous section.
        3. int msgsz - the size of the data part (mtext) of the message, in bytes.
        4. int msgflg - flags specifying how to send the message. may be a logical "or" of the following:
            IPC_NOWAIT - if the message cannot be sent immediately, without blocking the process, return ‘-1’, and
            set errno to EAGAIN.
            to set no flags, use the value ‘0’.
    /
   rc = msgsnd(queue_id, msg, strlen(msg->mtext)+1, 0);
   if (rc == -1) {
       perror("main: msgsnd");
       exit(1);
   }
   free(msg);
   printf("message placed on the queue successfully.n");

    recv_msg = (struct msgbuf
)malloc(sizeof(struct msgbuf)+strlen("hello
       world"));

    /
    int msgtyp - Type of message we wish to read. may be one of:
        1. 0 - The first message on the queue will be returned.
        2. a positive integer - the first message on the queue whose type (mtype) equals this integer (unless a certain flag is set in msgflg, see below).
        3. a negative integer - the first message on the queue whose type is less then or equal to the absolute value of this integer.
   
/
    /
    int msgflg - a logical ‘or’ combination of any of the following flags:
        IPC_NOWAIT - if there is no message on the queue matching what we want to read, return ‘-1’, and set errno to ENOMSG.
        MSG_EXCEPT - if the message type parameter is a positive integer, then return the first message whose type is NOT equal to the given integer.
        MSG_NOERROR - If a message with a text part larger then ‘msgsz’ matches what we want to read, then truncate the text when copying the message to our msgbuf structure. If this flag is not set and the message text is too large, the system call returns ‘-1’, and errno is set to E2BIG.
   
/
    / use ‘0’ in the message type parameter, and use no flags (0). /
    rc = msgrcv(queue_id, recv_msg, strlen("hello world")+1, 0, 0);
   if (rc == -1) {
       perror("main: msgrcv");
       exit(1);
   }
   printf("msgrcv: received message: mtype ‘%d’; mtext ‘%s’n",
       recv_msg->mtype, recv_msg->mtext);
   return 0;
}





/
queue_sender.c - a program that reads messages with one of 3 identifiers
to a message queue.
/
#include <stdio.h> / standard I/O functions. /
#include <stdlib.h> / malloc(), free() etc. /
#include <sys/types.h> / various type definitions. /
#include <sys/ipc.h> / general SysV IPC structures /
#include <sys/msg.h> / message queue functions and structs. /
#include "queue_defs.h" / definitions shared by both programs /
int main(int argc, char argv[])
{
    int queue_id; /
ID of the created queue. /
    struct msgbuf
msg; / structure used for sent messages. /
    /struct msgbuf recv_msg;/
    int i; /
loop counter /
    int rc; /
error code retuend by system calls. /
    /
create a public message queue, with access only to the owning user. /
    queue_id = msgget(QUEUE_ID, IPC_CREAT | IPC_EXCL | 0600);
    if (queue_id == -1) {
        perror("main: msgget");
        exit(1);
    }
    printf("message queue created, queue id ‘%d’.n", queue_id);
    msg = (struct msgbuf
)malloc(sizeof(struct msgbuf)+MAX_MSG_SIZE);
    / form a loop of creating messages and sending them. /
    for (i=1; i <= NUM_MESSAGES; i++) {
        msg->mtype = (i % 3) + 1; / create message type between ‘1’ and ‘3’ /
        sprintf(msg->mtext, "hello world - %d", i);
        rc = msgsnd(queue_id, msg, strlen(msg->mtext)+1, 0);
        if (rc == -1) {
            perror("main: msgsnd");
            exit(1);
        }
    }
    / free allocated memory. /
    free(msg);
    printf("generated %d messages, exiting.n", NUMMESSAGES);
    return 0;
}

__


/
queue_reader.c - a program that reads messages with a given identifier
off of a message queue.
/
#include <stdio.h> / standard I/O functions. /
#include <stdlib.h> / malloc(), free() etc. /
#include <unistd.h> / sleep(), etc. /
#include <sys/types.h> / various type definitions. /
#include <sys/ipc.h> / general SysV IPC structures /
#include <sys/msg.h> / message queue functions and structs. /
#include "queue_defs.h" / definitions shared by both programs /
void main(int argc, char argv[])
{
    int queue_id; /
ID of the created queue. /
    struct msgbuf
msg; / structure used for received messages. /
    int rc; / error code returned by system calls. /
    int msg_type; / type of messages we want to receive. /
    / read message type from command line /
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <message type>n", argv[0]);
        fprintf(stderr, " <message type> must be between 1 and 3.n");
        exit(1);
    }
    msg_type = atoi(argv[1]);
    if (msg_type < 1 || msg_type > 3) {
        fprintf(stderr, "Usage: %s <message type>n", argv[0]);
        fprintf(stderr, " <message type> must be between 1 and 3.n");
        exit(1);
    }
    / access the public message queue that the sender program created. /
    queue_id = msgget(QUEUE_ID, 0);
    if (queue_id == -1) {
        perror("main: msgget");
        exit(1);
    }
    printf("message queue opened, queue id ‘%d’.n", queue_id);
    msg = (struct msgbuf)malloc(sizeof(struct msgbuf)+MAX_MSG_SIZE);
    /
form a loop of receiving messages and printing them out. /
    while (1) {
        rc = msgrcv(queue_id, msg, MAX_MSG_SIZE+1, msg_type, 0);
        if (rc == -1) {
            perror("main: msgrcv");
            exit(1);
        }
        printf("Reader ‘%d’ read message: ‘%s’n", msg_type, msg->mtext);
        /
slow down a little… /
        sleep(1);
    }
    /
NOT REACHED */
}