2014-05-01 4 views
0

Je suis en train d'utiliser l'interprocessus de Boost pour l'accès à la mémoire partagée.
Ce que j'essaie de faire est de stocker une carte dans la mémoire partagée et d'accéder à partir d'un processus à l'autre. Ci-dessous la partie du code où j'essaie de faire la même chose -
Boost problème de mémoire partagée interprocess

SharedMemoryManager.h

#ifndef SHARED_MEMORY_MANAGER_H 
#define SHARED_MEMORY_MANAGER_H 

#include <boost/interprocess/managed_shared_memory.hpp> 
#include <boost/interprocess/containers/string.hpp> 
#include <boost/interprocess/allocators/allocator.hpp> 
#include <boost/interprocess/sync/named_semaphore.hpp> 
#include <boost/interprocess/containers/map.hpp> 

enum RangeBound { START, END, SINGLE }; 

typedef struct { 
    std::string code; 
    RangeBound flag; 
} ZipRangeInfo; 

typedef std::string RangeKeyType; 
typedef std::pair<const RangeKeyType, ZipRangeInfo> RangeValueType; 

typedef boost::interprocess::allocator<RangeValueType, boost::interprocess::managed_shared_memory::segment_manager> RangeBasedShmemAllocator; 

typedef boost::interprocess::map<RangeKeyType, ZipRangeInfo, std::less<RangeKeyType>, RangeBasedShmemAllocator> SharedRangeBasedMap; 

class SharedMemoryManager { 

private: 
    static boost::interprocess::managed_shared_memory *segment; 
    static RangeBasedShmemAllocator *alloc_range_map; 
public: 
    static char* get_range_based_routing_code(char *dataItem, char *fileName); 
    static SharedRangeBasedMap* get_range_based_routing_table(char *fileName); 
    static void load_range_based_routing_table(const char *fileName); 
}; 

#endif //SHARED_MEMORY_MANAGER_H 

et SharedmemoryManager.cpp

#include "SharedMemoryManager.h" 

const std::string shm_code_util("SharedMemoryUtil"); 

//Initializing shared memory of size 1 GB. 
boost::interprocess::managed_shared_memory *SharedMemoryManager::segment = 
     new boost::interprocess::managed_shared_memory(
       boost::interprocess::open_or_create, "CRS", 1024 * 1024 * 1024); 
RangeBasedShmemAllocator *SharedMemoryManager::alloc_range_map = 
     new RangeBasedShmemAllocator(segment->get_segment_manager()); 

// Method definitions 

char* SharedMemoryManager::get_range_based_routing_code(char *dataItem, 
     char *fileName) { 

    char* result = NULL; 
    // Postal Code Scrubbing Logic 
    if (dataItem == NULL) 
     return NULL; 
    try { 
     char *dataIt = (char *) calloc(strlen(dataItem) + 1, sizeof(char)); 
     strcpy(dataIt, dataItem); 

     SharedRangeBasedMap *routing_table = get_range_based_routing_table(
       fileName); 
     std::cout << "Hash Table Size :" << routing_table->size(); 
     if (routing_table != NULL && routing_table->size() > 0) { 
      RangeKeyType key(dataItem); 
      SharedRangeBasedMap::const_iterator routing_entry = 
        routing_table->lower_bound(key); 
      std::cout << "Got iterator"; 
      if (routing_entry == routing_table->end()) { 
       return NULL; 
      } 
      if (routing_entry->first == key 
        || routing_entry->second.flag == END) { 
       result = (char *) routing_entry->second.code.c_str(); 
      } 
     } 
     free(dataIt); 

     return result; 
    } catch (std::exception &e) { 
     throw; 
    } 
} 

SharedRangeBasedMap* SharedMemoryManager::get_range_based_routing_table(
     char *fileName) { 

    boost::interprocess::named_semaphore sync_semaphore(
      boost::interprocess::open_or_create, "LoadFilesSemaphore", 1); 
    sync_semaphore.wait(); 
    try { 
     SharedRangeBasedMap *routing_table = segment->find_or_construct< 
       SharedRangeBasedMap>(fileName)(std::less<RangeKeyType>(), 
         *alloc_range_map); 
     if (routing_table->size() == 0) { 
      load_range_based_routing_table(fileName); 
     } 
     sync_semaphore.post(); 

     return routing_table; 
    } catch (...) { 
     std::cout << "An exception was thrown; couldn't load post codes."; 
     sync_semaphore.post(); 
     return NULL; 
    } 
    return NULL; 
} 

void SharedMemoryManager::load_range_based_routing_table(const char *fileName) { 

    SharedRangeBasedMap *range_based_map = NULL; 
    range_based_map = segment->find_or_construct<SharedRangeBasedMap>(
       fileName)(std::less<RangeKeyType>(), *alloc_range_map); 


    // Build the hash if empty 
    if (range_based_map != NULL && range_based_map->size() == 0) { 
     //logic to populate the map - tested to work correctly 
    } 
} 


Le problème que je suis face à face est que le premier processus qui appelle get_range_based_routing_code, initialisant ainsi la mémoire partagée et peupler la carte, est en mesure de récupérer la valeur de la carte alors que tout appel ultérieur à get_range_based_routing_code rencontre une erreur de segmentation.
En ajoutant cout déclarations, je suis en mesure de déduire que la ligne ci-dessous est celui qui provoque l'erreur (ou est la ligne LSAT d'exécution) -

SharedRangeBasedMap::const_iterator routing_entry = 
        routing_table->lower_bound(key); 

Im ayant du mal à comprendre cela et mon inexpérience en C++ n'aide pas. Des pointeurs?

+0

'nombre entier = 0; if (count> 0) {... 'condition n'est jamais remplie. Quel est ton code _real_? Aussi, il semble bien préférable de déplacer l'initialisation de 'SharedMemoryManager :: segment' sous le mutex aussi (oh, oui, utilisez un mutex nommé au lieu d'un sémaphore nommé (1) parce que c'est plus simple/plus clair.) – sehe

+0

Je me suis déshabillé load_range_based_routing_table parce qu'il a été testé pour fonctionner correctement et aussi parce qu'il avait beaucoup de logique métier. J'ai apporté des modifications à load_range_based_routing_table pour supprimer l'oubli susmentionné. – ping

Répondre

2

Vous devez également attribuer le type de clé à la zone de mémoire partagée.

Il existe un certain nombre d'échantillons IPC Boost qui définissent un shared_string à cette fin. Vous pouvez réutiliser ceci.


va de même pour l'intérieur std::string du type ZipRangeInfo. Oui, c'est beaucoup de travail et gênant. En pratique, vous pouvez remplacer ZipRangeInfo::code par une taille statique boost::array<char, ...> ou char[N]

+0

L'allocation du type de clé à partir de la mémoire partagée a fonctionné. Upvoting et acceptation. Merci! – ping

Questions connexes