4

I have a quick question for those familiar with inter-process communication.

Situation

  • I have a program (program A) which I can add some code to, but very limited. This is the main program that generate a lot of data.
  • The way the data is formulated is limited, so I would like to create a second program (program B) and hence need to get data from A to B. And even sometimes cause A to run some functions with no return value.
  • I am aware of Named pipes, however I feel they might be bulky? - not sure though - I have for instance the following concerns (may be unfounded):
    1. data flow => convert to binary -> place data in memory -> server Read -> convert to string -> through probably a switch statement determine what is requested -> get what is requested -> convert to binary -> place in memory -> read by client and convert to string / some acceptable format.
    2. It has to use basically switch statements on both sides and if you want a different format of info other than string, you will need to take this into consideration
    3. one message might have to wait for another to complete, so it might be slower during a lot of calls to it at the same time? - not sure though
  • Other inter process communication methods probably has the same problem.
  • Better solution I think would be to create an "object" - class. And share the object memory address between programs, thereby theoretically "merging" the A and B then:

    1. There is no problem with encode and decode issues etc
    2. Data is simply requested / invoked through calling a function.
    3. The function return the proper type and no need to establish what the correct type is (i.e. bool / int / string / double etc)

    I understand that this also has several problems, i.e. if object gets removed from memory location by main / another program accessing it.

Question

  • What is the best way to solve this problems:
  • Is there an invoke option in C++ that will allow me to write and read from a memory address? at the moment:
    1. I can access same object between A and B, but I can't write / read as that will throw an exception. So basically can I through simple invoke perhaps read / write to this object?
    2. I am aware of WriteProcessMemory function - but this is not what I want - i.e. I don't necessarily want to change memory values, merely access data / invoke actions from B that A will perform.
  • Is there a simple and easy way of doing this? I am aware of something called boost, but don't know anything about it - is this my best option? -> i.e. should I investigate this as my best solution?

Thank you in advance for any advise on this issue.

DaClan
  • 329
  • 2
  • 15
  • *"I am aware of something called boost"*. Good. But the best thing would be to use it: http://boost.org. And... surprise! There's something that may help you through your problem: [Boost.Interprocess](http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess.html) – Mark Garcia Jun 27 '14 at 07:55
  • You can send binary data through pipes just fine. In fact to the OS what goes through a pipe is a raw stream of bytes. However you want to use a proper serialization format. How about "Cap'n Proto", which has the benefit for your situation, that the wire format is the same as the data in memory. – datenwolf Jun 27 '14 at 08:25

3 Answers3

1

Boost.Interprocess had many ways to share data between processes, one of which is shared_memory

example taken from boost, where a program acts as server or client for the same memory object (depending on whether an argument is given or not)

include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <cstring>
#include <cstdlib>
#include <string>

int main(int argc, char *argv[])
{
   using namespace boost::interprocess;

   if(argc == 1){  //Parent process
      //Remove shared memory on construction and destruction
      struct shm_remove
      {
         shm_remove() { shared_memory_object::remove("MySharedMemory"); }
         ~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
      } remover;

      //Create a shared memory object.
      shared_memory_object shm (create_only, "MySharedMemory", read_write);

      //Set size
      shm.truncate(1000);

      //Map the whole shared memory in this process
      mapped_region region(shm, read_write);

      //Write all the memory to 1
      std::memset(region.get_address(), 1, region.get_size());

      //Launch child process
      std::string s(argv[0]); s += " child ";
      if(0 != std::system(s.c_str()))
         return 1;
   }
   else{
      //Open already created shared memory object.
      shared_memory_object shm (open_only, "MySharedMemory", read_only);

      //Map the whole shared memory in this process
      mapped_region region(shm, read_only);

      //Check that memory was initialized to 1
      char *mem = static_cast<char*>(region.get_address());
      for(std::size_t i = 0; i < region.get_size(); ++i)
         if(*mem++ != 1)
            return 1;   //Error checking memory
   }
   return 0;
}
Pieter
  • 17,435
  • 8
  • 50
  • 89
  • Thanks Pieter. I will try this. I haven't done shared memory before. Is my idea correct that you can place an object in the shared memory location and provided both A and B has a "prototype" of the construction of the object - i.e. both refer to same class and by merely creating pointers on both sides you can use it? or is it more like "Named pipes" where memory is given a name and both A and B watch for changes in shared memory. I assumed it was the former. I will investigate into Boost further. Thanks!!!! – DaClan Jun 27 '14 at 08:27
  • 2
    @DaClan It is possible to create classes inside shared memory, you have to be careful with synchronisation issues though, take a look at http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess/managed_memory_segments.html#interprocess.managed_memory_segments.managed_memory_segment_features.allocation_types (better yet, take some time to read through the whole Interprocess documentation, this is no trivial task) – Pieter Jun 27 '14 at 08:37
1

Simplify!

In general, shared state might be a bad idea, won't be well testable, and might wreak havoc of unmanageable architecture as global variables can do.

The ØMQ guide might help you to get a grip on possible solutions. In general, if you have no special requirements, use message passing. ØMQ "sockets" are fast, quite robust, and require very little code to get started.

Update: readymade: msgpack-rpc or protobuf-remote

Dmitry Ledentsov
  • 3,620
  • 18
  • 28
  • Thanks @Dmitry. I am aware of this solution. But unless I am mistaken you still sit with a issue of encoding and decoding, in the sense that there are 100 functions to call, so you will have to establish which function has actually been called by the message that was sent - I have started down a similar root with named pipes before, but it seems cumbersome to code as you will need to write encoding and decoding functions on both the server and client side. This might be easy solution!! But is it necessarily quick in performance/efficient to write? - isn't a better solution a shared class? – DaClan Jun 27 '14 at 08:14
  • there are simple solutions to that: RPC: [msgpack-rpc](https://github.com/msgpack-rpc/msgpack-rpc-cpp) or [protobuf-remote](https://code.google.com/p/protobuf-remote/wiki/GettingStartedCpp) – Dmitry Ledentsov Jun 27 '14 at 08:16
  • with proper separation of concerns you won't need to program coding and decoding functions. The declarations of your interfaces would be at the same time used by the implementation of coding and decoding, and the C++ code – Dmitry Ledentsov Jun 27 '14 at 08:17
  • 1
    Or "Cap'n Proto – RPC" – datenwolf Jun 27 '14 at 08:26
  • @datenwolf I am not familiar with Cap'n Proto at all. I will investigate this too. Thanks! – DaClan Jun 27 '14 at 08:43
0

Are you making a software for customer, or just for yourself for data analysis? If just for your self, you can write the data into your hard disk, and separate your analysis into two steps.

jiandingzhe
  • 1,881
  • 15
  • 35
  • It is a test project. If possible it could be sold. Primarily it is for a finance company that I work for. Program A is a third party program that allow C++ code to be added to a limited extend. There is really too much data coming through to write all on a HDD. Program A has about 100 function which mainly calls a server at another location (i.e. data stored off site). I have asked for an API function, but they are relunctant to give me direct access. So program A talks to server C... to copy all that data, will not work unfortunately. – DaClan Jun 27 '14 at 08:37
  • Ps. to get some of this data has crucial time implications. So my solution must be both easily implemented (i.e. don't want to use messaging as that will require writing each function twice - once for the message - another for the decoding side to understand which function should be called) and quick. – DaClan Jun 27 '14 at 08:40
  • @DaClan I am not very familiar at inter-process communications. What about using TCP connection? You can make your program as a server, and make the thing in program A as a client. – jiandingzhe Jun 29 '14 at 08:25