Reputation: 2262
I am trying to understand message queues. In the examples I saw, the msg
strunct would have only one more attribute except of the first one (the type) which must be long
. So, it would be something like struct msg{long mtype; char text[100]};
.
I tried to add a new int
attribute, x
to see if I recieve both the text and the number and it worked.
Is this how message queues are supposed to work? Can I have as many attributes as I want in my struct
?
And, also, is it ok to call the msgrcv
and msgsnd
functions with the length parameter set to sizeof(send) - sizeof(send.x)
because I know that the sizeof a struct isn't always the same as the sum of the sizeof
of each attribute?
Thank you.
int main(){
struct msg{
long mtype;
char text[100];
int x;
};
int key = ftok(".", 10);
int qid = msgget(key, 0666|IPC_CREAT);
int pid = fork();
if(pid == 0){
struct msg send;
send.mtype = 1;
strcpy(send.text, "hello");
send.x = 99;
if(msgsnd(qid, (void*)&send, sizeof(send) - sizeof(send.x), 0)<0){
printf("Error child: ");
}
}
else{
struct msg recieve;
if(msgrcv(qid, (void*)&recieve, sizeof(recieve) - sizeof(recieve.x), 1, 0)<0){
perror("Error parent: ");
};
printf("text: %s\nnumber: %d", recieve.text, recieve.x);
}
return 0;
}
Upvotes: 1
Views: 1222
Reputation: 33944
From the man page, in:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msgp
is defined as:
The msgp argument is a pointer to a caller-defined structure of the following general form:
struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1]; /* message data */ };
Bold is mine
The major point here being the struct is caller-defined. So as long as the input struct (sent by msgsnd
) and output struct (received by msgrcv
) are the same, the data following mtype
can be anything you want (as long as you specify the size correctly). For your case, you really only need:
msgsnd(qid, (void*)&send, sizeof(send) - sizeof(send.mtype), 0)
and
msgrcv(qid, (void*)&recieve, sizeof(recieve) - sizeof(send.mtype), 1, 0)
Upvotes: 4
Reputation: 9416
The char[] is just a placeholder, you can have whatever you want in the structure after the required long mtype field. The size on the msgsnd() call does NOT include mtype.
You almost had it correct.
Here is a working version:
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int main(void){
struct msg {
long mtype;
char text[100];
int x;
};
size_t sz = sizeof(struct msg) - sizeof(long); <=== /* SIZE */
int key = ftok(".", 10);
int qid = msgget(key, 0666|IPC_CREAT);
int pid = fork();
if (pid == 0){
struct msg send;
send.mtype = 1;
strcpy(send.text, "hello");
send.x = 99;
if (msgsnd(qid, (void*)&send, sz, 0)<0){
perror("Error child: ");
}
} else {
struct msg recieve;
if(msgrcv(qid, (void*)&recieve, sz, 1, 0)<0){
perror("Error parent: ");
};
printf("text: %s\nnumber: %d\n", recieve.text, recieve.x);
}
return 0;
}
Upvotes: 1
Reputation: 83577
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
Since the msgp
parameter is declared as const void*
, you can use whatever data type you want. There is nothing that says it has to be a struct
with just a long
and a char[]
. This means you can just do sizeof(send)
. You do not need to adjust for the extra struct member that you are sending. In fact, doing so will cause problems because the entire struct will not be handled. The only thing that matters is that msgrcv()
uses the same struct as the previous msgsnd()
. See this example.
Upvotes: 0