Re: shm_open and mmap: Invalid argument?
Re: shm_open and mmap: Invalid argument?
- Subject: Re: shm_open and mmap: Invalid argument?
- From: Tim Hewett <email@hidden>
- Date: Mon, 21 Feb 2005 00:47:23 +0000
Mark,
It looks like off_t casting is a red herring, I deleted the cast in mine
and it still worked ok.
I am using mmap() on a real file, my shared memory is
file-backed. This is because the System V IPC is not great under
OS X in my experience and using file-backed shared memory seemed
the only option for the size of shared memory I need. System V IPC
semaphores were/(are?) the worst, under 10.2 they caused a dual CPU
Mac to panic every time, it seems to be well worth avoiding the
subsystem
and use something a bit more universal.
Now that I know about the Posix shm_open() call (thanks to this thread)
I am now experimenting with it, for Ethan's benefit here are the results
as they seem to be different to what he reports:
1. For the process initially creating the shared memory, the shm_open()
works and the mmap() works (no "Invalid argument" error). I had been
calling shm_unlink() right after the shm_open() call, so that the shared
memory is always deleted after the last process using it terminates
(even if it crashes) but that was failing with EINVAL. It was moved to
after the mmap() and now works. That doesn't make much sense but
that is how it is, it seems as if Posix shared memory is in some kind of
limbo state meaning it can't be unlinked until after it has been mapped.
2. If an ordinary file path is used for shm_open(), it fails. Changing
the
name to "/1" or similar makes it work fine.
3. The other processes sharing the shared memory in my application
are all child processes and they mmap() it using the file descriptor
they
inherit from the main parent. Here I have the same problem as Ethan -
the mmap always fails with EINVAL, why this only happens in the
subprocesses is a mystery.
This is my experimental code:
Parent process (shared memory creator) - works fine:
if ( (bufferFd = shm_open( "/1", O_RDWR | O_CREAT, 0700 )) == -1 ) {
// Error handling here
return;
}
if ( fcntl( bufferFd, F_SETFD, 1 ) == -1 ) {
// Error handling here
}
if ( ftruncate( bufferFd, (off_t)size ) == -1 ) {
// Error handling here
return;
}
if ( (buf = mmap( NULL, (size_t)size, PROT_READ | PROT_WRITE,
MAP_SHARED, bufferFd, 0 )) == (void *)-1 ) {
// Error handling here
return;
}
if ( mlock( (caddr_t)buf, (size_t)size ) == -1 ) {
// Error handling here
return;
}
if ( shm_unlink( "/1" ) == -1 ) {
// Error handling here
}
Child process - inherits shared memory file descriptor, mmap() returns
EINVAL but the preceding call to fstat() works fine so the descriptor is
being inherited ok (not much else can be wrong):
if ( fstat( inherited_fd, &filestat ) == -1 ) {
// Error handling here
exit( -1 );
}
if ( (buf = mmap( NULL, filestat.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED, inherited_fd, (off_t)0 )) == (void *)-1 ) {
// Error handling here
exit( -1 );
}
So this has kind of moved things along slightly, in that the creator
can shm_open/fcntl/ftruncate/mmap/mlock/shm_unlink the shared
memory, but the children can't mmap it yet even though they have
successfully inherited the descriptor.
My OS is 10.3.8 incidentally, not tried 10.2 yet.
Tim.
On 20 Feb 2005, at 20:42, Mark Williamson wrote:
It looks like the final parameter to mmap() (i.e. an integer constant
of value 0) needs to be cast to type off_t to suit the mmap function
definition. The off_t type is a 64 bit "long long" while your constant
is 32 bits, Lord only knows what'll be in the other 32 bits received
by mmap()...
Did this work for you? I thought that casts were supposed to be done
automatically in these situations (assuming you included the right
header
files!!!).
Cheers,
Mark
HTH,
Tim.
On 20 Feb 2005, at 20:03, email@hidden wrote:
I am trying to implement some shared memory between a set of
processes.
I don't really care if it's file-backed or not -- these regions are
not going to be particularly large, I just want low latency
communication between the processes.
I've already got things working with the SysV interfaces shmget and
shmat, but Mac OS X is configured with a very low number of
concurrently active regions per process (I think 8?) and I don't want
other users to have to tinker with kernal configuration settings, so
I'm switching to the POSIX interface instead. (It was also quite
annoying that SysV regions are left in memory after all references
are
gone. Further, OS X doesn't provide the ipcs utility, I had to
download it myself in order to kill the regions manually. (thanks to
whoever ported that utility... I had trouble finding it the first
time
and I can't find it again now :( )
Anyway, now mmap always returns Invalid Argument when it is passed a
file descriptor produced by shm_open. I saw somewhere that OS
X/darwin
doesn't support mmap with device files, does this imply no non-file
backed regions? Further, calls to close() and shm_unlink() after the
mmap error return Invalid Argument themselves, and then on the next
run
(using the same name) shm_open returns File Exists. So it appears
the
POSIX interface will also leave these regions floating around after
the
process ends and all references are removed, although I had read
somewhere it wouldn't. (Especially annoying since I did make the
calls
to close and shm_unlink)
What's going on?
Here's the code sample for the region in question:
int fd;
if(name.size()>=MAX_NAME_LEN)
cerr << "*** WARNING RCRegion named " << name << " will be clipped
to
" << name.substr(0,MAX_NAME_LEN-2) << endl;
id.key[0]='/'; //one page I read said for best portability, names
should start with '/'... ?
strncpy(id.key+1,name.c_str(),MAX_NAME_LEN-2);
id.key[MAX_NAME_LEN-1]='\0';
cout << "Name is " << id.key << endl;
if(create) {
if((fd=shm_open(id.key,O_RDWR|O_CREAT|O_EXCL,0666))<0) {
perror("Getting new region (shm_open)");
exit(EXIT_FAILURE);
}
} else {
if((fd=shm_open(id.key,O_RDWR,0666))<0) {
perror("Getting existing region (shm_open)");
exit(EXIT_FAILURE);
}
}
cout << "fd is " << fd << endl;
base=static_cast<char*>(mmap(NULL,sz,PROT_READ|PROT_WRITE,MAP_SHARED,
fd
,
0));
if (base == reinterpret_cast<char*>(-1)) {
perror("Attaching region (mmap)");
if(close(fd)<0)
perror("Warning: Closing temporary file descriptor from
shm_open");
if(shm_unlink(id.key)<0)
perror("Warning: Shared memory unlink (shm_unlink)");
exit(EXIT_FAILURE);
}
if(close(fd)<0) {
perror("Warning: Closing temporary file descriptor from shm_open");
}
Thank you for your time!
-ethan
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
mark.williamson@cl.c
am.ac.uk
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-kernel mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden