2013-02-08 10 views
8

Sto tentando di sostituire la chiamata di sistema originale mmap() su un fd pre-identificato tramite LD_PRELOAD, in modo che il processo che lo chiama possa leggere un oggetto memoria condiviso creato in precedenza da un altro processo con boost::interprocess. Va tutto bene, tranne quando cerco finalmente di leggere la memoria di MMap. In tal caso, il primo processo si interrompe con un errore di segmentazione. Quale potrebbe essere la ragione? Non ho bisogno di permessi di scrittura sull'oggetto memoria condivisa.mmap() con LD_PRELOAD e boost :: interprocess non funziona

Questo è il codice nella libreria precaricata:

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

Il codice del programma creare l'oggetto di memoria condivisa è:

//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()); 

Il codice del programma (che segfaults) provare a leggere la memoria condivisa sopra è:

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

Puoi mostrare il codice della tua sostituzione 'mmap'? Potrebbe esserci qualcosa di sbagliato in questo. –

+0

Lo farò il prima possibile. – Martin

+0

sei sicuro di voler sostituire OGNI chiamata a singolo mmap() nel tuo processo con la tua implementazione? Se stai usando il trucco LD_PRELOAD, è esattamente quello che succederà ... –

risposta

7

Il tuo problema è che si sta effettivamente ret urna un riferimento a un locale, ma in un modo un po 'offuscato. Il tuo override mmap() ha uno interprocess::shared_memory_object e interprocess::mapped_region sullo stack, che vengono distrutti quando si ritorna al client. Durante la distruzione, i wrapper boost rimuoveranno l'area di memoria, quindi non sarà più valido accedervi nel codice client. Come semplice correzione, rendere statiche queste variabili impedirebbe l'errore del segmento, anche se a seconda della struttura dell'applicazione potrebbe essere necessaria una soluzione più complicata.