message queue. msgsend msgrcv. System V IPC system calls in C (Linux)

4.8k views Asked by At

Hi I'm working with some shared memory where different processes read and write data. I'm using a message queue to store messages of when data has changed between read and write operations.

/* struct that defines a message */
struct msgbuf{
  long mtype;         /* must be positive */
  int childId;        //ID of child sending message
  int bufferChanged;  //Buffer at which value was changed
  int beforeValue;    //Value before child sleeps
  int afterValue;     //Value after child sleeps
};

So while reading and writing and checking for changes the processes store messages the following way

struct msgbuf msg = {BUFFER_CHANGED, id, position, read, bufferArr[position]};
if(msgsnd(msqid, &msg, sizeof(msg), 0)== -1){
  perror("msgsnd in read.write");
}

This is working fine. Oh by the way here's how I create the message queue.

#define BUFFER_CHANGED 1

qKey = ftok("./", 'A');

msqid = msgget(qKey, (IPC_CREAT | 0666));

/*Perform the following if the call is unsuccessful.*/
if(msqid == -1){
  printf ("\nThe msgget call failed, error number = %d\n", errno);
}
/*Return the msqid upon successful completion.*/
else{
  printf ("\nMessage queue successful. The msqid = %d\n", msqid);
  //exit(0);
}

So my problem is that I'm not quite sure how to retrieve messages from the queue and display them on the screen. I've been reading up on msgrcv() system call, but it's not very clear to me.

rc = msgrcv(msqid, &msg, sizeof(msg), BUFFER_CHANGED, IPC_NOWAIT);

rc is an int since msgrcv() returns an int. How do I point this int to the actual message? How to I read contents from the message so I can display them? I'm assuming this should be done in some sort of loop.

2

There are 2 answers

0
Carl Norum On

The return value is an int because it's telling you how much data it read into your message buffer - in your case you want to see 4 * sizeof(int) come back for a full message. If rc comes back as -1, you have an error. If rc came back as a positive number, at least some of the fields of msg will have the received message data.

Check out the man page for more details.

0
mortal On
rc = msgrcv(msqid, &msg, sizeof(msg), BUFFER_CHANGED, IPC_NOWAIT)

The msg contains the data that you want to display on the screen. Since IPC_NOWAIT is used, the function returns immediately without blocking. The rc value will be -1 if no msg was read, else it will be the number of bytes read from the msgq.