2013-02-08 11 views
8

Ich versuche, den ursprünglichen Systemaufruf mmap() auf einem vor-identifizierten FD über LD_PRELOAD zu ersetzen, damit der aufrufende Prozess ein gemeinsam genutztes Speicherobjekt lesen kann, das zuvor erstellt wurde ein anderer Prozess mit boost::interprocess. Alles läuft gut, außer wenn ich endlich versuche, die gespeicherte Erinnerung zu lesen. In diesem Fall bricht der erste Prozess mit einem Segmentierungsfehler ab. Was könnte der Grund sein? Ich brauche keine Schreibrechte für das Shared-Memory-Objekt. mmap() mit LD_PRELOAD und boost :: interprocess funktioniert nicht

Dies ist der Code in der vorbelasteten Bibliothek:

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { 
    static void* (*o_mmap) (void *, size_t, int, int, int, off_t) = 
     o_mmap = (void*(*)(void *, size_t, int, int, int, off_t)) dlsym(RTLD_NEXT, "mmap"); 
    if (!o_mmap) 
     std::cout << "mmap() preload failed\n"; 
    if (fd != my_fd) 
     return (*o_mmap)(start, length, prot, flags, fd, offset); 
    interprocess::shared_memory_object shm (interprocess::open_only, "obj", interprocess::read_only); 
    interprocess::mapped_region region(shm, interprocess::read_only, 0, length, start); 
    std::cout << "mmap() overridden. addr =" << region.get_address() << " length: " << region.get_size() << " start: " << start << "\n"; 
    return region.get_address(); 
} 

Der Code des Programms Erzeugen des Shared-Memory-Objekt ist:

//Create a shared memory object. 
    shared_memory_object shm (create_only, "obj", 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()); 

Der Code des Programms (das Segfaults) versuchen, den gemeinsamen Speicher oben zu lesen ist:

int fd = open(my_file, O_RDONLY); 

    void* addr = mmap(0, 1000, PROT_READ, MAP_SHARED, fd, 0); // Okay 

    //Check that memory was initialized to 1 
    char *mem = static_cast<char*>(addr); 
    for(std::size_t i = 0; i < 1000; ++i) 
    if(*mem++ != 1) // SEGFAULT! 
     return 1; //Error checking memory 
+0

Können Sie den Code Ihres 'mmap' Ersatzes zeigen? Da könnte etwas nicht stimmen. –

+0

Ich werde so schnell wie möglich. – Martin

+0

Möchten Sie wirklich JEDEN einzelnen mmap() - Aufruf in Ihrem Prozess durch Ihre eigene Implementierung ersetzen? Wenn Sie den LD_PRELOAD-Trick verwenden, wird genau das passieren ... –

Antwort

7

Ihr Problem ist, dass Sie effektiv ret sind einen Verweis auf eine lokale, aber auf eine leicht verschleierte Weise. Ihre mmap() - Überschreibung hat einen interprocess::shared_memory_object und interprocess::mapped_region auf dem Stapel, die zerstört werden, wenn Sie zum Client zurückkehren. Während der Zerstörung heben die Boost-Wrapper den Speicherbereich auf, so dass es nicht länger gültig ist, in Ihrem Client-Code darauf zuzugreifen. Eine einfache Lösung wäre es, diese Variablen statisch zu machen, um den Seg-Fehler zu verhindern, obwohl abhängig von der Struktur Ihrer Anwendung eine kompliziertere Lösung erforderlich sein könnte.