views:

503

answers:

4

Our app depends on an external, 3rd party-supplied configuration (including custom driving/decision making functions) loadable as .so file.

Independently, it cooperates with external CGI modules using a chunk of shared memory, where almost all of its volatile state is kept, so that the external modules can read it and modify it where applicable.

The problem is the CGI modules require a lot of the permanent config data from the .so as well, and the main app performs a whole lot of entirely unnecessary copying between the two memory areas to make the data available. The idea is to make the whole Shared Object to load into Shared Memory, and make it directly available to the CGI. The problem is: how?

  • dlopen and dlsym don't provide any facilities for assigning where to load the SO file.
  • we tried shmat(). It seems to work only until some external CGI actually tries to access the shared memory. Then the area pointed to appears just as private as if it was never shared. Maybe we're doing something wrong?
  • loading the .so in each script that needs it is out of question. The sheer size of the structure, connected with frequency of calls (some of the scripts are called once a second to generate live updates), and this being an embedded app make it no-go.
  • simply memcpy()'ing the .so into shm is not good either - some structures and all functions are interconnected through pointers.
+2  A: 

Placing actual C++ objects in shared memory is very, very difficult, as you have found. I would strongly recommend you don't go that way - putting data that needs to be shared in shared memory or a memory mapped file is much simpler and likely to be much more robust.

anon
+2  A: 

The first thing to bear in mind when using shared memory is that the same physical memory may well be mapped into the two processes virtual address space as different addresses. This means that if pointers are used anywhere in your data structures, they are going to cause problems. Everything must work off an index or an offset to work correctly. To use shared memory, you will have to purge all the pointers from your code.

When loading a .so file, only one copy of the .so file code is loaded (hence the term shared object).

fork may also be your friend here. Most modern operating systems implement copy-on-write semantics. This means that when you fork, your data segments are only copied into separate physical memory when one process writes to the given data segment.

doron
A: 

You need to implement object's Serialization Serialization function will convert your object into bytes, then you can write bytes in SharedMemory and have your CGI module to deserialize bytes back to object.

Wizzard
+1  A: 

I suppose the easiest option would be to use memory mapped file, what Neil has proposed already. If this option does not fill well, alternative is to could be to define dedicated allocator. Here is a good paper about it: Creating STL Containers in Shared Memory

There is also excellent Ion Gaztañaga's Boost.Interprocess library with shared_memory_object and related features. Ion has proposed the solution to the C++ standardization committee for future TR: Memory Mapped Files And Shared Memory For C++ what may indicate it's worth solution to consider.

mloskot
While it doesn't directly answer my question, I guess it's the nearest it gets. I have yet to see a useful call of shmat() with the second parameter different than NULL.
SF.
Leave it NULL and let the system to decide location of memory segment being atached and return its address to you.
mloskot