IPC:Message Queues:<sys/msg.h>

Two (or more) processes can exchange information via access to a common system message queue.

message.gif

Before a process can send or receive a message, the queue must be initialized (through the msgget function see below) Operations to send and receive messages are performed by the msgsnd() and msgrcv() functions, respectively.

When a message is sent, its text is copied to the message queue. The msgsnd() and msgrcv() functions can be performed as either blocking or non-blocking operations.

IPC signal and other mechanisms can be employed to implement such transfer.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Initialising the Message Queue

The msgget() function initializes a new message queue:

int msgget(key_t key, int msgflg)

Example:
#include <sys/ipc.h>; 
#include <sys/msg.h>;

...


key_t key; /* key to be passed to msgget() */
int msgflg /* msgflg to be passed to msgget() */
int msqid; /* return value from msgget() */

...
key = ...
msgflg = ...

if ((msqid = msgget(key, msgflg)) == &ndash;1)
{
perror("msgget: msgget failed");
exit(1);
} else
(void) fprintf(stderr, &ldquo;msgget succeeded");
...



-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Controlling message queues



The msgctl() function alters the permissions and other characteristics of a message queue.



int msgctl(int msqid, int cmd, struct msqid_ds *buf )



cmd:
IPC_STAT
-- Place information about the status of the queue in the data structure pointed to by buf. The process must have read permission for this call to succeed.
IPC_SET
-- Set the owner's user and group ID, the permissions, and the size (in number of bytes) of the message queue. A process must have the effective user ID of the owner, creator, or superuser for this call to succeed.
IPC_RMID
-- Remove the message queue specified by the msqid argument.

Example:

#include<sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
...
if (msgctl(msqid, IPC_STAT, &buf) == -1) {
perror("msgctl: msgctl failed");
exit(1);
}
...
if (msgctl(msqid, IPC_SET, &buf) == -1) {
perror("msgctl: msgctl failed");
exit(1);
}
...
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Sending and Receiving Messages

 

The msgsnd() and msgrcv() functions send and receive messages
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

int msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);


Example:


#include <sys/types.h> 
#include <sys/ipc.h>
#include <sys/msg.h>

...

int msgflg; /* message flags for the operation */
struct msgbuf *msgp; /* pointer to the message buffer */
int msgsz; /* message size */
long msgtyp; /* desired message type */
int msqid /* message queue ID to be used */

...

msgp = (struct msgbuf *)malloc((unsigned)(sizeof(struct msgbuf)
- sizeof msgp->mtext + maxmsgsz));

if (msgp == NULL) {
(void) fprintf(stderr, "msgop: %s %d byte messages.\n",
"could not allocate message buffer for", maxmsgsz);
exit(1);

...

msgsz = ...
msgflg = ...

if (msgsnd(msqid, msgp, msgsz, msgflg) == -1)
perror("msgop: msgsnd failed");
...
msgsz = ...
msgtyp = first_on_queue;
msgflg = ...
if (rtrn = msgrcv(msqid, msgp, msgsz, msgtyp, msgflg) == -1)
perror("msgop: msgrcv failed");
...
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Example:




Send.c



#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>

#define MSGSZ 128


/*
* Declare the message structure.
*/

typedef struct msgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;

main()
{
int msqid;
int msgflg = IPC_CREAT | 0666;
key_t key;
message_buf sbuf;
size_t buf_length;

/*
* Get the message queue id for the
* "name" 1234, which was created by
* the server.
*/
key = 1234;

(void) fprintf(stderr, "\nmsgget: Calling msgget(%#lx,\
%#o)\n",
key, msgflg);

if ((msqid = msgget(key, msgflg )) < 0) {
perror("msgget");
exit(1);
}
else
(void) fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid);


/*
* We'll send message type 1
*/

sbuf.mtype = 1;

(void) fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid);

(void) strcpy(sbuf.mtext, "Did you get this?");

(void) fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid);

buf_length = strlen(sbuf.mtext) + 1 ;



/*
* Send a message.
*/
if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0) {
printf ("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length);
perror("msgsnd");
exit(1);
}

else
printf("Message: \"%s\" Sent\n", sbuf.mtext);

exit(0);
}




Recv.c


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

#define MSGSZ 128


/*
* Declare the message structure.
*/

typedef struct msgbuf {
long mtype;
char mtext[MSGSZ];
} message_buf;


main()
{
int msqid;
key_t key;
message_buf rbuf;

/*
* Get the message queue id for the
* "name" 1234, which was created by
* the server.
*/
key = 1234;

if ((msqid = msgget(key, 0666)) < 0) {
perror("msgget");
exit(1);
}


/*
* Receive an answer of message type 1.
*/
if (msgrcv(msqid, &rbuf, MSGSZ, 1, 0) < 0) {
perror("msgrcv");
exit(1);
}

/*
* Print the answer.
*/
printf("%s\n", rbuf.mtext);
exit(0);
}




arrow
arrow
    全站熱搜

    phchiu 發表在 痞客邦 留言(0) 人氣()