9

(std) 文字列の共有メモリ ベクトルを管理するクラスを作成しようとしています。

typedef boost::interprocess::allocator<std::string, boost::interprocess::managed_shared_memory::segment_manager> shmem_allocator;
typedef boost::interprocess::vector<std::string, shmem_allocator> shmem_vector;

shmem_mgr::shmem_mgr() :
    shmem_(create_only, SHMEM_KEY, SHMEM_SIZE),
    allocator_(shmem_.get_segment_manager())
{
    mutex_  = shmem_.find_or_construct<interprocess_mutex>(SHMEM_MUTEX)();
    condition_ = shmem_.find_or_construct<interprocess_condition>(SHMEM_CONDITION)();
    //buffer_ is of type shmem_vector
    buffer_  = shmem_.construct<shmem_vector>(SHMEM_BUFFER_KEY)(allocator_);
}

void shmem_mgr::run() {
    running_ = true;

    while(running_) {
        scoped_lock<interprocess_mutex> lock ( *mutex_ );

        int size = buffer_->size();

        log_.debug() << size << " queued request(s) found" << std::endl; //LINE 27
        for(int i=0; i<size; i++) {
            log_.debug() << buffer_->at(i); // at() crashes my app
        }

        buffer_->clear(); //so does clear()
        condition_->wait (lock);
    }
}

クライアントは文字列をベクターに正常に追加し (デバッグのためにバッファーからその文字列を読み取ることにも成功します)、マネージャー (上記のコード) はシグナル (条件変数) を受信し、ベクターに文字列があることを書き込みます (27 行目)、しかしat()、アプリケーションを介してその文字列を取得しようとするとクラッシュします。


編集:私は、の使用std::stringが不可能であることを理解しましたstring。この場合のためだけに、boost ipc にコンテナーがあります。これは、(boost/std) 文字列のベクトルが必要であるという事実を変更しません...


Q :共有メモリ間で文字列を渡すにはどうすればよいですか? それらをshmemのバッファ(一度に1つ以上格納できる)に格納し、2番目のプロセスでフェッチする必要があります-それが要件です。入力と出力は常にstd::string同じですが、shmem の内部表現は異なる場合があります。

4

3 に答える 3

14

ドキュメントから。

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/allocators/allocator.hpp>

int main ()
{
   using namespace boost::interprocess;
   //Typedefs
   typedef allocator<char, managed_shared_memory::segment_manager>
      CharAllocator;
   typedef basic_string<char, std::char_traits<char>, CharAllocator>
      MyShmString;
   typedef allocator<MyShmString, managed_shared_memory::segment_manager>
      StringAllocator;
   typedef vector<MyShmString, StringAllocator>
      MyShmStringVector;

   //Open shared memory
   //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;

   managed_shared_memory shm(create_only, "MySharedMemory", 10000);

   //Create allocators
   CharAllocator     charallocator  (shm.get_segment_manager());
   StringAllocator   stringallocator(shm.get_segment_manager());

   //This string is in only in this process (the pointer pointing to the
   //buffer that will hold the text is not in shared memory).
   //But the buffer that will hold "this is my text" is allocated from
   //shared memory
   MyShmString mystring(charallocator);
   mystring = "this is my text";

   //This vector is only in this process (the pointer pointing to the
   //buffer that will hold the MyShmString-s is not in shared memory).
   //But the buffer that will hold 10 MyShmString-s is allocated from
   //shared memory using StringAllocator. Since strings use a shared
   //memory allocator (CharAllocator) the 10 buffers that hold
   //"this is my text" text are also in shared memory.
   MyShmStringVector myvector(stringallocator);
   myvector.insert(myvector.begin(), 10, mystring);

   //This vector is fully constructed in shared memory. All pointers
   //buffers are constructed in the same shared memory segment
   //This vector can be safely accessed from other processes.
   MyShmStringVector *myshmvector =
      shm.construct<MyShmStringVector>("myshmvector")(stringallocator);
   myshmvector->insert(myshmvector->begin(), 10, mystring);

   //Destroy vector. This will free all strings that the vector contains
   shm.destroy_ptr(myshmvector);
   return 0;
}
于 2012-10-24T01:57:41.523 に答える
1

共有可能なstlクラス用のカスタムアロケータが必要です。アロケータで定義された自己ベースのポインタ(ACEとブーストにはこれらがあります)が必要です。反対側では、(CONTIGUOUS)共有メモリは通常異なるアドレスにあります。共有メモリ割り当てサブシステム(ヒープマネージャー)も必要です(アロケーターが割り当てる)-すべての重要な低レベルコードですが、最も確実に実行可能であり、一度取得すると、どこでも使用できます。それをすべて行う場合は、非フラット構造の変位((CONTIGUOUS !!)ヒープ領域の先頭から)を渡すだけで済みます。

オブジェクト内の「ポインタ」が自己ベースであり、フラットでない部分の不連続な部分が1つの大きな連続した部分からのものであるという条件で、キューやその他の必要なすべてのものを作成できます。

std :: stringを使用することはできません。これは、割り当てを制御しない限り、標準文字列のメモリは共有メモリとは何の関係もないためです。他のstl構造でも同じです。

所有権の問題を解決/合意することも(いつものように)不可欠です

于 2012-10-20T22:52:37.150 に答える
1

boost::interprocess::managed_shared_memory を使用できます。次のプログラムは、2 つのプロセス間で boost::interprocess::string を渡します。私のマシン(Ubuntu Linux)で正常に動作します。managed_shared_memory を使用して、ベクターまたはオブジェクトを渡すことができます。boost::interprocess::string には c_str() メソッドがあります。

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>

int main(int argc, char *argv[])
{
  using namespace boost::interprocess;
  typedef boost::interprocess::allocator<char, boost::interprocess::managed_shared_memory::segment_manager> CharAllocator;
  typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> string;
  if(argc == 1){  //Parent process

      boost::interprocess::shared_memory_object::remove("MySharedMemory");

      //Create a shared memory object.
      managed_shared_memory shm (create_only, "MySharedMemory", 1024);

      string *s = shm.find_or_construct<string>("String")("Hello!", shm.get_segment_manager());
      std::cout << *s << std::endl;

      //Launch child process
      std::string s1(argv[0]); s1 += " child ";
      if(0 != std::system(s1.c_str()))
         return 1;
  }
  else{
      //Open already created shared memory object.
      managed_shared_memory shm (open_only, "MySharedMemory");
      std::pair<string *,std::size_t> ret = shm.find<string>("String");
      std::cout << *(ret.first) << std::endl;
  }
  return 0;
}
于 2012-10-25T09:22:21.427 に答える