2014-06-27 146 views
4

对于那些熟悉进程间通信的人,我有一个快速的问题。通过内存共享C++对象

形势

  • 我有一个计划(方案一),我可以添加一些代码,但非常有限。这是生成大量数据的主要程序。
  • 数据的表达方式是有限的,所以我想创建第二个程序(程序B),因此需要从A到B获取数据。甚至有时会导致A运行一些没有返回值的函数。
  • 我知道命名管道,但我觉得他们可能会体积庞大? - 不知道 - 我有例如以下问题(可能没有根据):
    1. 数据流=>转换为二进制 - >将数据放在内存中 - >服务器读取 - >转换为字符串 - >通过可能是一个开关语句确定请求 - >获取请求 - >转换为二进制 - >在内存中放置 - >由客户端读取并转换为字符串/一些可接受的格式。
    2. 它必须基本上使用双方的开关语句,如果你想要一个不同于字符串的信息格式,你需要考虑这一点
    3. 一条消息可能要等待另一条消息完成,所以它在同一时间的很多电话中可能会更慢? - 不确定
  • 其他进程间通信方法可能有同样的问题。
  • 更好的解决方案我认为会创建一个“对象”类。与程序之间共享对象的内存地址,从而在理论上“合并” A和B,则:

    1. 没有与编码和解码的问题等
    2. 数据只是要求没有问题/通过调用一个函数调用。
    3. 函数返回正确的类型,也不需要建立正确的类型是什么(即布尔/ INT /串/双等)

    我明白,这也有几个问题,即,如果对象被删除从内存位置由主/另一个程序访问它。

问题

  • 什么是解决这一问题的最佳途径:
  • 是否有在C++中调用的选项,让我写和从存储器地址读?此刻:
    1. 我可以访问A和B之间的同一个对象,但是我不能写/读,因为这会抛出异常。那么基本上我可以通过简单的调用或者读写这个对象吗?
    2. 我知道WriteProcessMemory函数 - 但这不是我想要的 - 即我不一定要更改内存值,只是访问数据/调用B将执行的操作。
  • 有没有一个简单而简单的方法呢?我知道一些叫做boost的东西,但是对它不了解 - 这是我最好的选择吗? - >即我应该调查这是我最好的解决方案吗?

非常感谢您对此问题的任何建议。

+0

*“我知道一些叫做boost的东西”*。好。但最好的办法是使用它:http://boost.org。而且......惊喜!有些东西可以帮助你解决问题:[Boost.Interprocess](http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess.html) –

+0

你可以通过管道发送二进制数据就好了。实际上,对于操作系统而言,通过管道的东西是一个原始的字节流。但是你想使用正确的序列化格式。 “Cap'n Proto”如何对您的情况有好处,那么线格式与内存中的数据相同。 – datenwolf

回答

1

Boost.Interprocess有许多方法来共享进程之间的数据,其中之一是从升压,其中一个程序充当服务器或客户端为相同的存储对象(根据参数值是否给出或采取shared_memory

示例不)

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; 
} 
+0

感谢彼得。我会试试这个。我之前没有做过共享记忆。我的想法是正确的,你可以放置一个对象在共享内存位置,并提供A和B都有一个对象构造的“原型” - 即两个引用相同的类,并只在两边创建指针,你可以使用它?还是更像是“命名管道”,在这里命名内存,A和B都监视共享内存的变化。我认为这是前者。我会进一步调查Boost。谢谢!!!! – DaClan

+2

@DaClan可以在共享内存中创建类,但您必须小心同步问题,请查看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(更好的是,花一些时间来阅读整个Interprocess文档,这不是一件容易的事情) – Pieter

+0

感谢Pieter,这将有很大的帮助! – DaClan

1

简化!

一般来说,shared state可能是一个坏主意,不会很好测试,并可能会造成无法管理的体系结构的浩劫,因为global variables可以做到。

ØMQ guide可能会帮助您掌握可能的解决方案。一般来说,如果您没有特殊要求,请使用消息传递。 ØMQ“套接字”是快速的,相当健壮的,并且需要很少的代码才能入门。

更新:成衣:msgpack-rpcprotobuf-remote

+0

谢谢@Dmitry。我知道这个解决方案。但是除非我弄错了,否则你仍然坐在一个编码和解码的问题上,因为有100个函数需要调用,所以你必须确定哪个函数实际上被发送的消息调用了 - 我已经开始了一个与之前的命名管道相似的根,但编码看起来很麻烦,因为您需要在服务器和客户端编写编码和解码功能。这可能是简单的解决方案!但是,编写它的性能/效率是否很快? - 共享课堂不是更好的解决方案吗? – DaClan

+0

有简单的解决方案:RPC:[msgpack-rpc](https:// github。com/msgpack-rpc/msgpack-rpc-cpp)或[protobuf-remote](https://code.google.com/p/protobuf-remote/wiki/GettingStartedCpp) –

+0

,将您不需要的问题妥善分离编程和解码功能。您的接口的声明将同时用于编码和解码的实现,并且C++代码 –

0

你在做一个软件客户,或者只是为自己进行数据分析?如果仅仅为了您自己,您可以将数据写入硬盘,并将分析分为两步。

+0

这是一个测试项目。如果可能的话可以出售。主要是为我工作的财务公司。程序A是第三方程序,允许C++代码被添加到有限的范围内。在硬盘上写入所有数据实在太多了。程序A具有大约100个主要在另一个位置调用服务器的功能(即,存储在异地的数据)。我已经要求提供一个API函数,但是它们是直接访问我的。因此,程序A与服务器C进行会谈以复制所有数据,不幸的是无法工作。 – DaClan

+0

Ps。获得这些数据有一些关键的时间影响。所以我的解决方案必须易于实现(即不要使用消息传递,因为这需要两次编写每个函数 - 一次用于消息 - 另一个用于解码侧以了解应该调用哪个函数)并且很快。 – DaClan

+0

@DaClan我对进程间通信不是很熟悉。怎么样使用TCP连接?您可以将您的程序作为服务器,并以程序A的身份作为客户端。 – jiandingzhe