Message Queues Lecturer: Erick Fredj 1 2003Dr. E. Fredj@ Message Queues IPC: message queues (MQ) • are software components used for interprocess (IPC) communication • utilize a queue for messaging, i.e. to pass – control – data • work asynchronously: – sender and receiver do not need to be connected at the same time 2 2003Dr. E. Fredj@ Message Queues The Basic idea: How does it work? • Two (or more) processes can exchange information via access to a common system message queue. • The sending process places via some (OS) message-passing module a message onto a queue which can be read by another process. • The receiving process reads the message from the queue • Each message is given an identification or type so that processes can select the appropriate message. • Process must share a common key in order to gain access to the queue in the first place. 3 2003Dr. E. Fredj@ Message Queues The Basic idea 4 2003Dr. E. Fredj@ Message Queues How to use MQ: #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> /* gets or create a MQ associated to a key */ int msgget(key_t key, int msgflg) /* controls the MQ data structure */ int msgctl(int ID, int cmd, struct msqid_ds *buf) /* stores a copy of the message on MQ */ int msgsnd(int ID, struct msgbuf *msgp, size_t msgsz,int msgflg) /* removes a message from the MQ */ ssize_t msgrcv(int ID, struct msgbuf *msgp, 5 Message Queues size_t msgsz, long msg-typ, int msgflg) Initializing the Message Queue int msgget(key_t key, int msgflg) key: – unique key (name) of the message queue – IPC_PRIVATE: special value for ’key’ – ignores msgflg and returns ID of message queue on success msgflg: – IPC_CREAT: create a new MQ unless it already exists – IPC_EXCL: useful in combination with IPC_CREAT, call of msgget() will fail if MQ already exists returns: – ID of message queue (on success) – -1 (otherwise) 6 Message Queues Send a message to a MQ: int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz,int msgflg ) msqid: ID of the message queue msgp: pointer to the message buffer struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[MSGSZ]; /* message data */ }; msgsz: size of the msgbuf-member ‘mtext’ in bytes msgflg: 0 or IPC_NOWAIT (return immediately, do not block) returns: – 0 (on success), – -1 (on error, errno is set) 7 Message Queues Read and remove a message from a MQ: int msgrcv (int msqid, struct msgbuf *msgp, int msgsz, int msgtype, int msgflg ) msqid, msgp, msgflg: c.f. msgsnd() msgsz: maximum length msgbuf-member ‘mtext’ in bytes msgtype: read only messages of this type from the queue returns: • 0 (on success), • -1 (on error, errno is set) 8 2003Dr. E. Fredj@ Message Queues Message control operations int msgctl ( int msqid, int cmd, struct msqid_ds *buf ) msqid: ID of the message queue cmd: – IPC_STAT – copy info from MQ data structure associated with msgid into ‚buf‘ – IPC_SET – write a few values of ‚buf‘ into MQ data structure, e.g. • msg_perm.uid • msg_perm.gid • msg_perm.mode /* only lowest 9-bits */ • msg_qbytes – IPC_RMID – remove the MQ buf: used for IPC_SET or IPC_STAT operations 9 Message Queues Example: msg_send.c #define MSGSZ 128 /* message size */ typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; /* Message structure */ int main(int argc, char* argv[]) { int msqid, msgflg = IPC_CREAT | 0666; key_t key = 1234; message_buf sbuf; size_t buf_length; fprintf(stderr, "\nmsgget: Calling msgget(%#lx,%#o)\n”,key,msgflg); msqid = msgget(key, msgflg ); sbuf.mtype = 1; /* We use message type 1 */ strcpy(sbuf.mtext, "Did you get this?"); /* this is the message */ buf_length = strlen(sbuf.mtext) + 1 ; msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT); /* Send a message */ printf ("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length); printf("Message: \"%s\" Sent\n", sbuf.mtext); }10 Message Queues Example: msg_rcv.c #define MSGSZ 128 typedef struct msgbuf { long mtype; char mtext[MSGSZ]; } message_buf; int main(int argc, char *argv[]) { int msqid; key_t key = 1234; message_buf rbuf; /* get the MQ with name “1234” created by the server */ msqid = msgget(key, 0666); /* get message with type 1 */ msgrcv(msqid, &rbuf, MSGSZ, 1, 0); printf("%s\n", rbuf.mtext); /* print answer */ exit(0); } 11 Message Queues