ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I've tried adding items to a message queue, and it works.
When I tried to remove it, it does not remove it.
The code I've used is given below. Isn't msgrcv() supposed to remove the items from the queue?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
main()
{
key_t key;
int msqid=0;
int pmb=934,inp=0,reply=1;
printf("Add to queue? [1=y/0=n]\n");
scanf("%d",&reply);
if (reply==1)
{
key = ftok("/home/beej/somefile", 'b');
msqid = msgget(key, 0666 | IPC_CREAT);
msgsnd(msqid, &pmb, sizeof(pmb), 0); /* put it onto the queue */
//printf("\nJust a sec...\n");
//scanf("%d",&inp);
}
printf("Removing it from queue\n");
/*-----------get it off the queue-----------*/
key = ftok("/home/beej/somefile", 'b');
msqid = msgget(key, 0666 | IPC_CREAT);
msgrcv(msqid, &pmb, sizeof(pmb), 2, 0); /* get it off the queue */
}/*main*/
When you write a message, part of that message is the message type. Ordinarily, one uses as the message, a struct, with the first element being the long int mtype field, followed by the message payload. This field must agree with the mtype parameter (4th param) in the call to msgrcv().
You seem to be using Beej's Guide (good), so go back and read more carefully.
I agree. Another good source of information is the man-pages.
I threw this little program together using the information I gathered (from the man-page):
Code:
#include <sys/msg.h>
#include <stdio.h>
#include <assert.h>
/* user defined data structure */
struct Data
{
int value;
};
const unsigned int DATA_TYPE = 5;
/* user defined Message Queue data transport buffer */
struct MsgBuf
{
long mtype;
struct Data data;
};
int main()
{
key_t key = ftok("somefile", 'b');
int msqid = msgget(key, 0666 | IPC_CREAT);
struct MsgBuf msg;
struct MsgBuf rcvmsg;
/* prepare message transport buffer that will be sent */
msg.mtype = DATA_TYPE;
msg.data.value = 123;
/* send the transport buffer */
printf("Writing to the queue...\n");
assert(msgsnd(msqid, &msg, sizeof(msg), 0) == 0);
/* receive the transport buffer */
printf("Removing from queue...\n");
assert(msgrcv(msqid, &rcvmsg, sizeof(rcvmsg), DATA_TYPE, 0) == sizeof(struct MsgBuf));
printf("value = %d\n", rcvmsg.data.value);
return 0;
}
I don't know if I did it correctly, that is, with respect to the MsgBuf struct I created, but the program does send and receive the data.
I agree. Another good source of information is the man-pages.
I threw this little program together using the information I gathered (from the man-page):
Code:
#include <sys/msg.h>
#include <stdio.h>
#include <assert.h>
/* user defined data structure */
struct Data
{
int value;
};
const unsigned int DATA_TYPE = 5;
/* user defined Message Queue data transport buffer */
struct MsgBuf
{
long mtype;
struct Data data;
};
int main()
{
key_t key = ftok("somefile", 'b');
int msqid = msgget(key, 0666 | IPC_CREAT);
struct MsgBuf msg;
struct MsgBuf rcvmsg;
/* prepare message transport buffer that will be sent */
msg.mtype = DATA_TYPE;
msg.data.value = 123;
/* send the transport buffer */
printf("Writing to the queue...\n");
assert(msgsnd(msqid, &msg, sizeof(msg), 0) == 0);
/* receive the transport buffer */
printf("Removing from queue...\n");
assert(msgrcv(msqid, &rcvmsg, sizeof(rcvmsg), DATA_TYPE, 0) == sizeof(struct MsgBuf));
printf("value = %d\n", rcvmsg.data.value);
return 0;
}
I don't know if I did it correctly, that is, with respect to the MsgBuf struct I created, but the program does send and receive the data.
Yay! I've done it at last. Thanks dwhitney67
I referred your code and was able to make corrections in mine. Took a long time though...
Corrected code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
main()
{
key_t key;
int msqid=0;
int pmb=934,inp=0,reply=1;
printf("Add to queue? [1=y]\n");
scanf("%d",&reply);
if (reply==1)
{
key = ftok("/home/beej/somefile", 'b');
msqid = msgget(key, 0666 | IPC_CREAT);
msgsnd(msqid, &pmb, sizeof(pmb), 0); /* put it onto the queue */
//printf("\nJust a sec...\n");
//scanf("%d",&inp);
printf("Remove from queue? [1=y]");
scanf("%d",&reply);
if (reply==1)
{
printf("Removing it from queue\n");
/*-----------get it off the queue-----------*/
//key = ftok("/home/beej/somefile", 'b');
//msqid = msgget(key, 0666 | IPC_CREAT);
msgrcv(msqid, &pmb, sizeof(pmb), 0, 0); /* get it off the queue */
}//if
}//if
}/*main*/
Just a couple of comments...
In many/most cases, the queue will be used by multiple processes, as distinct from your example code, where the producer and consumer are in a single process, and share the same queue ID variable. So, all processes will have to open a message queue, and acquire their own message queue IDs. Each process can open the queue with different permissions, as appropriate.
Along the same lines, again in most cases, the consumer will expect that the queue already exists, and not use the O_CREAT flag to open the queue. If this flag is not used, the msgget() call will fail, and return -1, which the caller can use to detect that there is probably no producer process, and act accordingly. The key returned by ftok() will probably be -1, if the path argument is a pathname of a non-existant file (as I suspect is the case in your example code). You should check the return values from these two functions, and take the appropriate branch as necessary.
There exists the handy tool ipcs, for examining and managing the state of queues and other IPC methods on a host.
--- rod.
Thanks for the info theNbomr. I just remembered that one thing I forgot to do in my sample program was to remove the message queue once I was done with it. This was quite apparent when I ran "ipcs".
@ the OP:
Make sure you insert this call when you are done using your message queue:
Thanks for posting....there's also the ipcrm tool which comes in handy.
@dwhitney67: Thanks for the msgctl(). Needed that one too. Works like a charm!
Code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
main()
{
key_t key;
int msqid=0;
int pmb=934,inp=0,reply=1;
printf("Add to queue? [1=y]\n");
scanf("%d",&reply);
if (reply==1)
{
key = ftok("/home/beej/somefile", 'b');
msqid = msgget(key, 0666 | IPC_CREAT);
msgsnd(msqid, &pmb, sizeof(pmb), 0); /* put it onto the queue */
//printf("\nJust a sec...\n");
//scanf("%d",&inp);
printf("Remove from queue? [1=y]");
scanf("%d",&reply);
if (reply==1)
{
printf("Removing it from queue\n");
/*-----------get it off the queue-----------*/
//key = ftok("/home/beej/somefile", 'b');
//msqid = msgget(key, 0666 | IPC_CREAT);
msgrcv(msqid, &pmb, sizeof(pmb), 0, 0); /* get it off the queue */
}//if
printf("Delete the queue? [1=y]");
scanf("%d",&reply);
if (reply==1)
{
msgctl(msqid, IPC_RMID, 0);
printf("Removed from queue");
}
}//if
}//main
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.