在附加进程时提升删除managed_shared_memory

rud*_*asi 1 c++ boost ipc shared-memory

我有2个进程,进程1创建一个boost managed_shared_memory段,进程2打开这个段.然后重新启动过程1并且过程1的开始具有以下内容,

struct vshm_remove
{
    vshm_remove() 
    { 
        boost::interprocess::shared_memory_object::remove("VMySharedMemory"); 
    }
    ~vshm_remove()
    {
        boost::interprocess::shared_memory_object::remove("VMySharedMemory"); 
    }
} vremover;
Run Code Online (Sandbox Code Playgroud)

我理解当进程1开始或结束时,将在我的共享内存上调用remove方法,但是如果没有附加进程2,它是否只能删除它?我使用以下内容附加到进程2中的共享内存,

boost::interprocess::managed_shared_memory *vfsegment;
vfsegment = new boost::interprocess::managed_shared_memory(boost::interprocess::open_only, "VMySharedMemory");
Run Code Online (Sandbox Code Playgroud)

我注意到无论进程2连接如何都删除了共享内存.

nkl*_*uza 8

我不相信文档中有任何提及shared_memory_object::remove如果附加了一个进程就会失败.

请参阅本节以获取参考:删除共享内存.尤其:

如果共享内存对象不存在或由另一个进程打开,则此函数可能会失败.

这意味着调用shared_memory_object::remove("foo")尝试删除名为"foo"的共享内存,无论如何.

该函数的实现(源于此处)反映了该行为:

inline bool shared_memory_object::remove(const char *filename)
{
   try{
      //Make sure a temporary path is created for shared memory
      std::string shmfile;
      ipcdetail::tmp_filename(filename, shmfile);
      return ipcdetail::delete_file(shmfile.c_str());
   }
   catch(...){
      return false;
   }
}
Run Code Online (Sandbox Code Playgroud)

根据我对已发布的生产代码的经验,在我不再需要访问共享内存之前,我已成功不进行调用shared_memory_object::remove.

我写了一个非常简单的示例主程序,您可能会发现它很有帮助.它将附加,创建或删除共享内存,具体取决于您运行它的方式.编译后,请尝试以下步骤:

  1. 使用c运行以创建共享内存(默认为1.0K)并插入虚拟数据
  2. 运行o以打开("附加到")共享内存并读取虚拟数据(默认情况下,读取将每10秒循环一次)
  3. 在单独的会话中,使用r运行以删除共享内存
  4. 再次使用o运行以尝试打开.请注意,这将(几乎可以肯定)失败,因为在上一步骤中(再次,几乎肯定)删除了共享内存
  5. 从第二步开始随意杀死该过程

至于为什么上面的步骤2继续能够在调用后访问数据shared_memory_object::remove,请参阅构建托管共享内存.特别:

当我们打开托管共享内存时

  • 打开共享内存对象.
  • 整个共享内存对象映射到进程的地址空间中.

最有可能的是,因为共享内存对象被映射到进程的地址空间,所以不再直接需要共享内存文件本身.

我意识到这是一个相当人为的例子,但我认为更具体的一些可能会有所帮助.

#include <cctype>   // tolower()
#include <iostream>
#include <string>
#include <unistd.h> // sleep()
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/managed_shared_memory.hpp>

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

  if (argc == 1) {
    cout << "usage: " << argv[0] << " <command>\n  'c'   create\n  'r'   remove\n  'a'   attach" << endl;
    return 0;
  }

  const char * shm_name = "shared_memory_segment";
  const char * data_name = "the_answer_to_everything";

  switch (tolower(argv[1][0])) {
    case 'c':
        if (shared_memory_object::remove(shm_name)) { cout << "removed: " << shm_name << endl; }
        managed_shared_memory(create_only, shm_name, 1024).construct<int>(data_name)(42);
        cout << "created: " << shm_name << "\nadded int \"" << data_name << "\": " << 42 << endl;
        break;
    case 'r':
      cout << (shared_memory_object::remove(shm_name) ? "removed: " : "failed to remove: " ) << shm_name << endl;
      break;
    case 'a':
      {
        managed_shared_memory segment(open_only, shm_name);
        while (true) { 
          std::pair<int *, std::size_t> data = segment.find<int>( data_name );
          if (!data.first || data.second == 0) {
            cerr << "Allocation " << data_name << " either not found or empty" << endl;
            break;
          }
          cout << "opened: " << shm_name << " (" << segment.get_segment_manager()->get_size()
               << " bytes)\nretrieved int \"" << data_name << "\": " << *data.first << endl;
          sleep(10);
        }
      }
      break;
    default:
      cerr << "unknown command" << endl;
      break;
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)