shared memory

hello,

trying to “install” two different shared memory objects (IN_BUF and OUT_BUF)
between two processes (process1 and process2) used up many hours by now. I
have not been able to figure out the solution. The problem seems to be
simple, so I’ll try to explain my basic program flow:

process1:

fd_IN = shm_open( “IN_BUFFER”, O_RDWR|O_CREAT, 0777 );
ftruncate( fd_IN, IN_BUF_size );
pointer_IN = mmap( 0, IN_BUF_size, flags, MAP_SHARED, fd_IN, 0 );

fd_OUT = shm_open( “OUT_BUFFER”, O_RDWR|O_CREAT, 0777 );
ftruncate( fd_OUT, OUT_BUF_size );
pointer_OUT = mmap( 0, OUT_BUF_size, flags, MAP_SHARED, fd_OUT, 0 );

and executed directly afterwards

process2:

fd_IN = shm_open( “IN_BUFFER”, O_RDWR, 0777 );
pointer_IN = mmap( 0, IN_BUF_size, flags, MAP_SHARED, fd_IN, 0 );

fd_OUT = shm_open( “OUT_BUFFER”, O_RDWR, 0777 );
pointer_OUT = mmap( 0, OUT_BUF_size, flags, MAP_SHARED, fd_OUT, 0 );

In my opinion, fd_IN and fd_OUT in process1 should match fd_IN and fd_OUT in
process2. But that is not the case. It is always: fd_OUT of process1 matches
fd_IN of process2. Why? I tried to change every possible setting and flag,
but it stays always like this.

Who can give me a hint?

Thank you.

Nnamdi

Nnamdi Kohn <nnamdi.kohn@tu-bs.de> wrote:

hello,

trying to “install” two different shared memory objects (IN_BUF and OUT_BUF)
between two processes (process1 and process2) used up many hours by now. I
have not been able to figure out the solution. The problem seems to be
simple, so I’ll try to explain my basic program flow:

process1:

fd_IN = shm_open( “IN_BUFFER”, O_RDWR|O_CREAT, 0777 );

According to Posix shared memory names should start with a leading / and
contain no other / characters. Otherwise the behaviour will be undefined.
(Under QNX6, IN_BUFFER would be created in the current working directory
(CWD) of the process that created it – this might not be found by
another process if started with a different CWD. If you did “/IN_BUFFER”,
it would be created in the expected place: /dev/shmem.)

ftruncate( fd_IN, IN_BUF_size );
pointer_IN = mmap( 0, IN_BUF_size, flags, MAP_SHARED, fd_IN, 0 );

fd_OUT = shm_open( “OUT_BUFFER”, O_RDWR|O_CREAT, 0777 );
ftruncate( fd_OUT, OUT_BUF_size );
pointer_OUT = mmap( 0, OUT_BUF_size, flags, MAP_SHARED, fd_OUT, 0 );

and executed directly afterwards

process2:

fd_IN = shm_open( “IN_BUFFER”, O_RDWR, 0777 );
pointer_IN = mmap( 0, IN_BUF_size, flags, MAP_SHARED, fd_IN, 0 );

fd_OUT = shm_open( “OUT_BUFFER”, O_RDWR, 0777 );
pointer_OUT = mmap( 0, OUT_BUF_size, flags, MAP_SHARED, fd_OUT, 0 );

In my opinion, fd_IN and fd_OUT in process1 should match fd_IN and fd_OUT in
process2. But that is not the case. It is always: fd_OUT of process1 matches
fd_IN of process2. Why? I tried to change every possible setting and flag,
but it stays always like this.

The actual number (fd) returned by shm_open() should not be expected to
match between the processes. What should be expected is that data written
to pointer_IN in process1 can be seen at the corresponding offset from
pointer_IN in process2 and vice versa. (Though, again, the actual values
of pointer_IN in the two different processes should also not be expected to
match.)

fds are assigned as available – if you opened or closed (or inherited
an extra open fd) in either process, you could quite easily get mismatched
fds back – what is important is that they both refer to the same memory
object. You make sure that happens by using names that start with a leading
slash as I suggested: “/IN_BUFFER” and “/OUT_BUFFER”.

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

Thank you, David. I didn’t mention, that I actually used the “/” at start of
the names and no other in the names. Actually, the fds match in the
different processes and so I thought, the memory locations (pointers) should
match also. But, nevertheless, the data written to pointer_IN of process1 is
not seen at the same offset at pointer_IN of process2. And that’s what I
don’t understand.

fds are assigned as available – if you opened or closed (or inherited
an extra open fd) in either process, you could quite easily get mismatched
fds back – what is important is that they both refer to the same memory
object. You make sure that happens by using names that start with a
leading
slash as I suggested: “/IN_BUFFER” and “/OUT_BUFFER”.

In reality I named the fds “fd_RxShMem” and “fd_TxShMem”, just to avoid my
own confusion. Is there a piece of code that certainly works for installing
two different ShMem objects between two processes? What else could the
reason be? Might it be that there is just ONE ShMem object possible per
process? Couldn’t be!

Thanks

Nnamdi

Nnamdi Kohn <nnamdi.kohn@tu-bs.de> wrote:

Thank you, David. I didn’t mention, that I actually used the “/” at start of
the names and no other in the names.

Ok – not what you showed, and not doing that could give exactly the
behaviour you described.

Do you do a shm_unlink() anywhere?

What does an “ls -l /dev/shmem” show after you’ve created the two
shared memory areas in process1?

I’ve included a pair of demo programs that use some shared memory
to communicate between them.

They just use one object – but using two objects should be no
different, just have to make sure you don’t get your names, fds,
and pointers confused.

In reality I named the fds “fd_RxShMem” and “fd_TxShMem”, just to avoid my
own confusion. Is there a piece of code that certainly works for installing
two different ShMem objects between two processes? What else could the
reason be? Might it be that there is just ONE ShMem object possible per
process? Couldn’t be!

No, you can have any number of shared memory objects between processes.


/*

  • shmemcreator.c
  • This module demonstrates shared memory and semaphores
  • by creating some shared memory and putting something in it (including
  • a semaphore structure). It then posts to the semaphore to tell other
  • processes that it is okay to read from the shared memory.
  • This one is meant to be run in tandem with shmemuser.c.
  • Run it as: shmemcreator shared_memory_object_name
  • Example: shmemcreator wally

*/

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>

/* shmem.h contains the structure that is overlayed on the shared memory */
#include “shmem.h”

/*

  • our global variables.
    */

char *progname = “shmemcreator”;

main( int argc, char *argv[] )
{
char *text = “Text by shmemcreator.c”;
int fd;
shmem_t *ptr;

if ( argc != 2 ) {
printf( “use: shmemcreator shared_memory_object_name\n” );
printf( “Example: shmemcreator wally\n” );
exit( EXIT_FAILURE );
}

/* create the shared memory object */

fd = shm_open( argv[1], O_RDWR | O_CREAT, S_IRWXU );
if ( fd == -1 ) {
printf( “%s: error creating the shared memory object ‘%s’: %s\n”,
progname, argv[1], strerror(errno) );
exit( EXIT_FAILURE );
}

/* set the size of the shared memory object */

ftruncate( fd, sizeof(shmem_t) );

/* get a pointer to a piece of the shared memory */

ptr = mmap( 0, sizeof(shmem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );

/*

  • initialize the semaphore
  • The 1 means it can be shared between processes. The 0 is the
  • count, 0 meaning sem_wait() calls will block until a sem_post()
  • is done.
    */
    sem_init( &ptr->semaphore, 1, 0 );

strcpy( ptr->text, text ); /* write to the shared memory */

printf( “%s: Shared memory created and semaphore initialized to 0.\n”
“%s: Wrote text ‘%s’ to shared memory.\n”
“%s: Sleeping for 20 seconds. While this program is sleeping\n”
“%s: run ‘shmemuser %s’.\n”,
progname, progname, ptr->text, progname, progname, argv[1] );
sleep( 20 );

printf( “%s: Woke up. Now posting to the semaphore.\n”, progname );
sem_post( &ptr->semaphore );

close( fd );
munmap( ptr, sizeof(shmem_t) );
shm_unlink( argv[1] );
}

/*

  • shmemuser.c
  • This module demonstrates shared memory and semaphores
  • by opening some shared memory, waiting on a semaphore (whose
  • semaphore structure is in the shared memory) and then printing out
  • what it finds in the shared memory.
  • This one is meant to be run in tandem with shmemcreator.c.
  • Run it as: shmemuser shared_memory_object_name
  • Example: shmemuser wally

*/

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>

/* shmem.h contains the structure that is overlayed on the shared memory */
#include “shmem.h”

/*

  • our global variables.
    */

char *progname = “shmemuser”;

main( int argc, char *argv[] )
{
int fd;
shmem_t *ptr;

if ( argc != 2 ) {
printf( “use: shmemuser shared_memory_object_name\n” );
printf( “Example: shmemuser wally\n” );
exit( EXIT_FAILURE );
}

/* open the shared memory object */

fd = shm_open( argv[1], O_RDWR, S_IRWXU );
if ( fd == -1 ) {
printf( “%s: error opening the shared memory object ‘%s’: %s\n”,
progname, argv[1], strerror(errno) );
exit( EXIT_FAILURE );
}

/* get a pointer to a piece of the shared memory */

ptr = mmap( 0, sizeof(shmem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );

/* wait on the semaphore */

printf( “%s: Waiting on the semaphore. Run ‘pidin’. I should be SEM blocked.\n”, progname );

sem_wait( &ptr->semaphore );

printf( “%s: The shared memory contains ‘%s’\n”, progname, ptr->text );

close( fd );
munmap( ptr, sizeof(shmem_t) );
}

-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.

David Gibbs <dagibbs@qnx.com> wrote:

oops forgot their common header file, shmem.h

#include <semaphore.h>

#define MAX_TEXT_LEN 100

typedef struct {
sem_t semaphore;
char text[MAX_TEXT_LEN+1];
} shmem_t;


-David

QNX Training Services
http://www.qnx.com/support/training/
Please followup in this newsgroup if you have further questions.