开发者

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

开发者 https://www.devze.com 2023-01-28 03:01 出处:网络
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 ano

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开发者_如何学Go 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.


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.


No, process do not (naturally) share memory. If boost is an option, so you can have a look on Boost.Interprocess for easy memory sharing.


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.


The trick here is that the memory has to be mapped the same way in both your processes. If your mapped shared memory can be arranged that way, it'll work, but I bet it'll be very difficult.

There are a couple of other possibilties. First one is to use an array; array indices will work across both processes.

You can also use placement new to make sure you're allocating objects at a known location within the shared memory, and use those offsets.


If you are on linux, you could use shared memory to store common data between processes. For general case, take a look into boost IPC library.

But pointer from one process can not be used in another (it's address can be used, if accessing IO, or some special devices)


If you use Qt4 there's QSharedMemory or you could use sockets and a custom serialization protocol.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号