Hi there, I'm hoping that some of you may be able
to help me with a problem I've encountered whilst trying to implement some Posix
shared memory.
I'm sure that the 'PTHREAD_PROCESS_SHARED' is still
not supported on OSX (at least not until Leopard..?) which rules out using
mutexes for shared memory between process. Therefore, I'm creating shared memory
using posix semaphores (sem_open, sem_wait and sem_close etc), with shm_open for
the shared memory.
I'm creating the shared memory on a single thread
in one application - I'll extend this once I've got the current system working.
However, my experiments show me the following:
1) If I create the shared memory (O_CREAT | O_RDWR
flags, 0x777 permissions) I obtain a valid shared memory ID. I can get the
'stat' structure of this 'file descriptor' which verifies that the permissions
are '0x777'. I also check whether the st_size value (a multiple of 4096 bytes
page size) is less than the size I've requested - in which case I call ftruncate
(successfully) on the shared memory ID. (The ftruncate is therefore only called
once, on the creation of the shared memory). I then map the memory using
mmap with (PROT_READ | PROT_WRITE and MAP_SHARED). I can then successfully write
to the shared memory segment.
2) Whether I leave the handle from 1) open or
not:
a) I can open multiple handles to the same shared
memory (using the same names for shared memory and mutex) with O_RDONLY access,
mmap-ing them with 'PROT_READ and MAP_SHARED'. I can also successfully read
the contents of the shared memory which correctly reflect what I wrote to it in
the first instance. And if I update the contents using the handle created in 1)
(assuming it's still open), the change is immediately reflected in all the
read-only handles. So far so good.
b) If I attempt to open another handle with
'O_RDWR', shm_open fails with 'EACCES'. This happens whether I've correctly
closed the handle in 1) using 'munmap' and 'close' or not.
*
The current behaviour would suggest that I can only
open shared memory with write permission when it's created. While that's open I
can't open any other file descriptors to that shared memory with write
permission; neither can I do it when the original descriptor is closed. I'm
wondering what I'm doing wrong...? Any help would be gratefully received -
thanks!
This is how I create the shared
memory:
[within constructor of shared memory
class]:
CLockMutex mutexSection(mutex); // mutex
created using posix semaphore. SharedMemID = shm_open(memname, O_CREAT |
O_RDWR, 0x777); // Create shared memory with read and write
access. struct stat fstats; fstat(SharedMemID, &fstats); // check to
see if the memory has been allocated and initialised if (fstats.st_size <
size) { // The file size was smaller than bytes requested -
use ftruncate and mmap to initialise the memory. int truncReturn
= ftruncate( SharedMemID, (off_t)size ); // Set the size of the file referenced
by SharedMemID to be 'size' bytes. // Map the
handle into memory smptr = mmap( 0, size, PROT_READ | PROT_WRITE,
MAP_SHARED, SharedMemID, 0 );
} // I
initialise the memory we've created here.
This all seems to work fine, and I can create an
access class (using my semaphore-implemented 'mutex') with which to access the
shared memory pointer and write to the memory. Viewing the memory in the
debugger shows that any writes are successful.
[creating read only shared memory using
same name]:
CLockMutex mutexSection(mutex); // mutex
created using posix semaphore. SharedMemID = shm_open(memname, O_RDONLY,
0x777); // Create shared memory with read access. struct stat
fstats; fstat(SharedMemID, &fstats); // check to see if the memory has
been allocated and initialised
// In this case, the size is already set and the
permissions are set to 0x777. Therefore no truncation is required - I just map
the memory:
smptr = mmap( 0, size, PROT_READ,
MAP_SHARED, SharedMemID, 0 );
I can create multiple instances of these using the
same name as the original shared memory - and they all work fine.
[creating write/read shared memory using
same name]:
CLockMutex mutexSection(mutex); // mutex
created using posix semaphore. SharedMemID = shm_open(memname, O_RDWR,
0x777); // Create shared memory with read and write access. - FAILS
HERE with errno = EACCES struct stat fstats; fstat(SharedMemID,
&fstats); // check to see if the memory has been allocated and
initialised
// In this case, the size is already set and the
permissions are set to 0x777. Therefore no truncation is required - I just map
the memory:
smptr = mmap( 0, size, PROT_READ,
MAP_SHARED, SharedMemID, 0 );
I'm puzzled as to why it fails - if anybody has any
suggestions I'd be very grateful. Meanwhile I'll try this without using the
semaphore-implemented mutex to see if that has any effect.
* NB Note that I haven't called sem_unlink at all
in this program. There's no ipcs-like tool I know of that lets you find how many
places have file descriptors open for a particular piece of shared memory.
Therefore, once I've got this working I intend to reference count the shared
memory (as part of a 'header') so that I can test when I need to called
sem_unlink in the destructor. Anyway - for now, I'm not calling 'sem_unlink' at
all - I'm just changing the names of the semaphore and shared memory every time
I debug....
|