2013-08-08 2 views
0

У меня есть 2 процесса, процесс 1 создает сегмент managed_shared_memory boost и процесс 2 открывает этот сегмент. Процесс-затем перезапущен и начало процесса 1 имеет следующее,Ускорение удаления managed_shared_memory при подключении процесса

struct vshm_remove 
{ 
    vshm_remove() 
    { 
     boost::interprocess::shared_memory_object::remove("VMySharedMemory"); 
    } 
    ~vshm_remove() 
    { 
     boost::interprocess::shared_memory_object::remove("VMySharedMemory"); 
    } 
} vremover; 

Я понимаю, что, когда процесс 1 начинает или заканчивает метод удалить будет называться на моей совместно используемой памяти, но не должен его только удалить его, если процесс 2 не прилагается к нему? Я прилагаю к совместно используемой памяти в процессе 2, используя следующее,

boost::interprocess::managed_shared_memory *vfsegment; 
vfsegment = new boost::interprocess::managed_shared_memory(boost::interprocess::open_only, "VMySharedMemory"); 

я заметил, что общая память удаляется независимо от процесса 2 соединены.

ответ

6

Я не верю, что в документации есть упоминание о том, что shared_memory_object::remove не удастся, если процесс присоединен.

См. Этот раздел для справки: Removing shared memory. В частности:

Эта функция может потерпеть неудачу, если общие объекты памяти не существует, или он открыт другим процессом.

Это означает, что вызов shared_memory_object::remove("foo") будет попытка удалить разделяемую память с именем «Foo» независимо от того, что.

Реализация этой функции (source here) отражает такое поведение:

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

В моем опыте выпущен код производства, я не имел успеха не призывающую shared_memory_object::remove, пока я больше не нужен доступ к совместно Память.

Я написал очень простой пример основной программы, которую вы можете найти полезной. Он будет прикреплять, создавать или удалять общую память в зависимости от того, как вы ее запускаете. После компиляции, попробуйте выполнить следующие действия:

  1. Запуск с с, чтобы создать общую память (1.0K по умолчанию) и вставьте фиктивные данные
  2. Run с о, чтобы открыть («присоединить к») общей памяти и прочитайте фиктивные данные (чтение будет происходить в цикле каждые 10 секунд по умолчанию)
  3. В отдельном сеансе выполните с r для удаления общей памяти
  4. Запустите снова, чтобы o попытался открыть. Обратите внимание на то, что это будет (почти наверняка) не потому, что общая память была (опять же, почти наверняка) удалены на предыдущем шаге
  5. Вы можете убить процесс на второй стадии

, почему шаг 2 выше продолжает получать доступ к данным по телефону shared_memory_object::remove, см. Constructing Managed Shared Memory.В частности:

Когда мы открываем управляемую совместно используемую память

  • открыт Общий объект памяти.
  • Весь объект общей памяти отображается в адресном пространстве процесса.

В основном, вероятно, потому, что общий объект памяти отображаются в процесс адресного пространства, сам общий файл памяти больше не требуется непосредственно.

Я понимаю, что это довольно надуманный пример, но я подумал, что может помочь что-то более конкретное.

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

Спасибо за ваш ответ, я также пошел, не удаляя сегмент разделяемой памяти, позволяя ему существовать. – rudasi

0

Еще одна интересная вещь - добавить еще один случай:

case 'w': 
    { 
    managed_shared_memory segment(open_only, shm_name); 
     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; 
     } 
     *data.first = 17; 
     cout << "opened: " << shm_name << " (" << segment.get_segment_manager()->get_size() 
      << " bytes)\nretrieved int \"" << data_name << "\": " << *data.first << endl; 
    } 
    break; 

Доп опции «ш» вызывает то, что память прилагается и написано «17» вместо («самый случайный случайный номер»). С этим вы можете сделать следующее:

Консоль 1: сделайте «c», затем «a». Сообщает, что память создана со значением 42.

Консоль 2: Сделайте «w». На консоли 1 вы увидите, что номер изменен.

Консоль 2: сделайте «r». Память успешно удалена, Консоль 1 все еще печатает 17.

Консоль 2: сделайте 'c'. Он будет сообщать о памяти как созданном со значением 42.

Консоль 2: Сделайте «а». Вы увидите 42, Console 1 все еще печатает 17.

Это подтверждает - пока это работает на всех платформах одинаково, но boost объявляет, что это так - вы можете использовать этот способ для отправки блоков памяти с одного обрабатывать другой, в то время как «продюсер» нуждается только в подтверждении того, что «потребитель» привязал блок, чтобы «производитель» теперь мог его удалить. Потребителю также не нужно отделять предыдущий блок перед присоединением следующего.

+0

Немного неясно, почему удаление может завершиться неудачно, если другой процесс использует эту память. Если это то же самое, что удаление файла, оно должно завершиться неудачно, если нет прав на удаление, или ресурс не существует под этим именем. Когда другой процесс использует его, он должен просто отсоединить его (в Windows он имитируется переименованием - я думаю, здесь может быть сложной частью). – Ethouris

Смежные вопросы