--- Begin Message ---
- From: Jose Miguel Goncalves <jose dot goncalves at inov dot pt>
- To: "J. Johnston" <jjohnstn at redhat dot com>
- Date: Thu, 26 Jun 2003 20:45:46 +0100
- Subject: Re: Message queue support
- References: <3EF98C51.30208@inov.pt> <3EF9E64F.3090009@redhat.com>
Jeff,
After setting up /dev/shm I could create a queue with mq_open(), and send
messages with mq_send(), but calling to mq_receive() returns errors - "Bad
address".
I attach the source code for the simple mqueue test application that I'm
using. I am compiling in a 2.4.21 linux kernel with:
$ gcc -static -nostdlib -g -Wall -D_REENTRANT
-I/usr/local/newlib/i686-pc-linux-gnu/include
/usr/local/newlib/i686-pc-linux-gnu/lib/crt0.o test_thread_queue.c
-L/usr/local/newlib/i686-pc-linux-gnu/lib -lpthread -lc -lgcc -o test_thread_queue
The same source compiled in a Sun Solaris 8 machine (with native support for
pthreads and mqueues) works fine.
Regards,
José Gonçalves
J. Johnston wrote:
Jose,
The mq_xxxx functions rely on /dev/shm being set up. The shmfs
support was
added as part of late 2.3.x kernels. Unlike glibc, newlib doesn't
bother hunting
for other locations. If you need to, change the mqlocal.h file to
reset the prefix name. If the problem is common-enough, I can make it a
compile
option and tie it to configuration.
Newlib linux support may not work 100% on older kernels. Newlib has
assumed 2.4 or greater
kernels and has not implemented back-level support like glibc does for
certain syscalls.
Older kernels can be used but an application may run into problems if
accessing features
requiring a more modern kernel.
-- Jeff J.
Jose Miguel Goncalves wrote:
Hi,
I would like to know in what level the newlib implementation of POSIX
message queues (mq_open, mq_send, etc..) depends on the linux kernel?
I've tried a simple example of using message queues and it fails on a
mq_open() call to create a queue. Digging in the source code with GDB
I see that mq_open() fails when it tries to open a shared memory file:
...
/* attempt to open the shared memory file for exclusive create
so we know
whether we are the owners or not */
fd = open (real_name, O_RDWR | O_CREAT | O_EXCL, mode);
if (fd < 0 && (oflag & O_EXCL))
{
/* we failed and the user wanted exclusive create */
...
Regards,
José Gonçalves
/*
* The classic producer-consumer example, implemented with message queues.
* All integers between 0 and MAX_MSG-1 should be printed exactly twice,
* once to the right of the arrow and once to the left.
*/
#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>
#include <sys/fcntl.h>
#include <pthread.h>
#define MAX_MSG 100
#define OVER (-1)
#define PMODE 0666
#define QUEUENAME "/myipc"
#define QUEUESIZE 10
/*
* Initialize a message queue
*/
static void
init_queue (mqd_t * mq_desc, int open_flags)
{
struct mq_attr attr;
/*
* Fill in attributes for message queue
*/
attr.mq_maxmsg = QUEUESIZE;
attr.mq_msgsize = sizeof (int);
attr.mq_flags = 0;
*mq_desc = mq_open (QUEUENAME, open_flags, PMODE, &attr);
if (*mq_desc == (mqd_t) - 1)
{
perror ("mq_open failure");
exit (EXIT_FAILURE);
};
}
/*
* Put an integer in the queue
*/
static void
put (mqd_t mq_desc, int data)
{
int status;
status = mq_send (mq_desc, (char *) &data, sizeof (int), 1);
if (status == -1)
perror ("mq_send failure");
}
/*
* Read and remove an integer from the queue
*/
static int
get (mqd_t mq_desc)
{
ssize_t num_bytes_received = 0;
int data=0;
num_bytes_received =
mq_receive (mq_desc, (char *) &data, sizeof (int), NULL);
if (num_bytes_received == -1)
perror ("mq_receive failure");
return (data);
}
/*
* Producer thread
*/
static void *
producer (void *data)
{
int n;
mqd_t mqfd;
init_queue (&mqfd, O_CREAT | O_WRONLY);
for (n = 0; n < MAX_MSG; n++)
{
printf ("%d --->\n", n);
put (mqfd, n);
}
put (mqfd, OVER);
/*
* Done with queue, so close it
*/
if (mq_close (mqfd) == -1)
perror ("mq_close failure");
return NULL;
}
/*
* Consumer thread
*/
static void *
consumer (void *data)
{
int d;
mqd_t mqfd;
init_queue (&mqfd, O_RDONLY);
while (1)
{
d = get (mqfd);
if (d == OVER)
break;
printf ("---> %d\n", d);
}
/*
* Done with queue, so close it
*/
if (mq_close (mqfd) == -1)
perror ("mq_close failure");
return NULL;
}
int
main (void)
{
pthread_t th_a, th_b;
void *retval;
printf ("MESSAGE QUEUE TEST STARTED\n");
/*
* Create the threads
*/
pthread_create (&th_a, NULL, producer, 0);
pthread_create (&th_b, NULL, consumer, 0);
/*
* Wait until producer and consumer finish.
*/
pthread_join (th_a, &retval);
pthread_join (th_b, &retval);
/*
* Delete the message queue
*/
mq_unlink (QUEUENAME);
return 0;
}
--- End Message ---