This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Message queue support


--- Begin Message --- 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 ---

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]