Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I pass an object to another process just passing its' pointer to a shared memory?

I have a very complicated class(it has unordered_map and so on on inside it) and I want to share an object of it withit two my processes. Can I simply pass just a pointer to it from one process to another? I think, no, but hope to hear "Yes!".

If "no", I'd be grateful to see any links how to cope in such cases. I need to have only one instance of this object for all processes because it's very large and all of the processes will work woth it for read only.

like image 990
flashnik Avatar asked Dec 04 '10 08:12

flashnik


2 Answers

You certainly can use IPC to accomplish this, and there are plenty of cases where multiple processes make more sense than a multithreaded process (at least one of the processes is built on legacy code to which you can't make extensive modifications, they would best be written in different languages, you need to minimize the chance of faults in one process affecting the stability of the others, etc.) In a POSIX-compatible environment, you would do

int descriptor = shm_open("/unique_name_here", O_RDWR | O_CREAT, 0777);

if (descriptor < 0) {
    /* handle error */
} else {

    ftruncate(descriptor, sizeof(Object));
    void *ptr = mmap(NULL, sizeof(Object), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, descriptor, 0);

    if (!ptr || ptr == MAP_FAILED)
        /* handle error */ ;

    Object *obj = new (ptr) Object(arguments);
}

in one process, and then

int descriptor = shm_open("/the_same_name_here", O_RDWR | O_CREAT, 0777);

if (descriptor < 0) {
    /* handle error */
} else {

  Object *obj = (Object *) mmap(NULL, sizeof(Object), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, descriptor, 0);

  if (!obj || obj == MAP_FAILED)
      /* handle error */ ;
}

in the other. There are many more options, and I didn't show the cleanup code when you're done, so you still ought to read the shm_open() and mmap() manpages, but this should get you started. A few things to remember:

  • /All/ of the memory the object uses needs to be shared. For example, if the Object contains pointers or references to other objects, or dynamically allocated members (including things like containers, std::string, etc.), you'll have to use placement new to create everything (or at least everything that needs to be shared with the other processes) inside the shared memory blob. You don't need a new shm_open() for each object, but you do have to track (in the creating process) their sizes and offsets, which can be error-prone in non-trivial cases and absolutely hair-pulling if you have fancy auto-allocating types such as STL containers.

  • If any process will be modifying the object after it's been shared, you'll need to provide a separate synchronization mechanism. This is no worse than what you'd do in a multithreaded program, but you do have to think about it.

  • If the 'client' processes do not need to modify the shared object, you should you should open their handles with O_RDONLY instead of O_RDWR and invoke mmap() without the PROT_WRITE permission flag. If the client processes might make local modifications that need not be shared with the other processes, invoke mmap() with MAP_PRIVATE instead of MAP_SHARED. This will greatly reduce the amount of synchronization required and the risks of screwing it up.

  • If these processes will be running on a multiuser system and/or the shared data may be sensitive and/or this is a high-availability application, you're going to want more sophisticated access control than what is shown above. Shared memory is a common source of security holes.

like image 179
spillner Avatar answered Sep 20 '22 05:09

spillner


No, the pointer is meaningless to the other process. The OS creates a separate address space for other processes; by default, they have no idea that other processes are running, or even that such a thing is possible.

like image 21
Karl Knechtel Avatar answered Sep 20 '22 05:09

Karl Knechtel