Re: shm_open and mmap: Invalid argument?
Re: shm_open and mmap: Invalid argument?
- Subject: Re: shm_open and mmap: Invalid argument?
- From: Ethan Tira-Thompson <email@hidden>
- Date: Mon, 21 Feb 2005 12:22:13 -0500
When your processes attach to the shared region how do they
know the size? Is it an application-wide constant? The call to
mmap has to have the size (since you can choose not to map
all the region). I've found that fstat() gets it fine on an inherited
shared memory descriptor from the parent.
I initially set up a shared memory region (called the RegionRegistry)
which then contains a list of available names (keys for SysV) and
sizes. Child processes then inherit this region through the fork.
(They don't inherit the file descriptor though, that's already been
closed immediately following region setup. Once the region is mmap'ed,
you can fork, and the child processes will also get the mapping... I
saw this explained explicitly for SysV, I don't think I saw it
mentioned for POSIX, but it seems to work fine.)
They can then advertise their regions and other processes will know how
to connect to them. This is more necessary under SysV, where key ID
numbers are arbitrary and you wouldn't really want to rely on a
particular number being available.
I wonder if you shm_open from a child process for a new (non-inherited)
region, if you can use fstat to determine the size of the region with
the resulting file descriptor. (from your test, I bet it would work)
I wouldn't need my RegionRegistry object at all in that case! (for
POSIX)
FYI, my intended usage is that most of the regions from the
RegionRegistry are RegionRegistries themselves, where related messages
and shared objects can be sent. If a message is sent, it's simply
dereferenced and it goes away. If a shared object is sent, the sender
and receiver keep a reference and can then keep up to date on that
object's information. For example, this is a robot based application,
so the main usage of this is to separate longer-term decision making
("Main") from the real-time motion execution ("Motion"). However, it's
a pain to have Main use only a message queue in order to send commands
to Motion because then you have to set up a communication protocol that
includes all the parameters for any time of motion you would ever want
to do, and then worry about serialization and parsing... blech.
Instead, we have a MotionCommand base class, with subclasses for
implementing different motions -- a specific pose, a sequence of poses,
pointing the head at things, walking, wagging the tail, etc. Using
polymorphism, the Motion process can simply call the updateJoints() on
each of these, and the object will do the appropriate calculations as
to where joints should be dynamically.
However, if main want to change something -- start walking a different
direction say -- it can call a function on its side of the shared
object (i.e. setTargetVelocity()), and then Motion will immediately
pick up on the new parameters stored in the walk object the next time
it's ready to call updateJoints().
No lag, no serialization. Very pretty. The only down side is these
shared objects must be self contained -- no pointers outside of the
region because they won't be available in other processes. Doesn't
turn out to be so terrible if you use a template argument to set the
maximum capacity of an internal storage member.
(updateJoints is actually updateOutputs because it includes control of
LEDs, and of course there are locking mechanisms I'm glossing over)
It is beginning to look like my approach with shm_unlink is going
to be a problem. My circumstance is that a controlling process
creates the shared segment and spawns short-lived children which
use the shared segment. Those children ought to be able to use
the inherited file descriptor that the parent received from shm_open()
when creating the region.
I'd suggest not bothering with file descriptors -- if the parent has
successfully mapped the region as shared, after the fork, the children
will also have the mapping and it will behave as expected (I have
verified this)
Here's the main():
http://cvs.tekkotsu.org/cgi-bin/viewcvs.cgi/Tekkotsu/project/local/sim/
Attic/sim.cc?rev=1.1.2.5&content-type=text/vnd.viewcvs-markup
It seems to me that the man page makes it clear that the shared
memory will persist even when all processes using it have terminated.
I figure that this means that the swap space will just go on getting
bigger
as more of these segments are left around.
I'm partly worried there's a system limit on how many regions can be
created. The (default) SysV limit was particularly burdensome (on OS
X). Of course, leaking swap is also not really a good thing. Surely
there's some way to list and remove regions? If not, there should be.
For my project, I've registered signal handlers for most issues and
then remove all regions from each process before the crash is complete.
This seems to prevent gdb from catching crashes though, which is a bit
of a pain, and isn't entirely foolproof depending on how hosed the
program is.
I suppose the fall back is to maintain a log on disk of region
creation/deletion, and then you can look at the log to see which
regions still need to be removed. That, of course, requires
forethought and responsibility on the application programmer. Seems
like it would be better to have a system interface for that... :-/
thanks,
-ethan
_______________________________________________
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