Domanda

Sto cercando di permettere a due processi diversi di comunicare utilizzando la memoria mappatura dello stesso file. Tuttavia, sto avendo qualche problema con questo. Ho la sensazione che questo ha a che fare con il modo in cui sto usando la chiamata open () e passando il mio descrittore di file per mmap.

Ecco il mio codice, si può vedere qualcosa di sbagliato con esso?

Il codice oggetto 1 di:

 16     FILE* temp = fopen(theSharedFileName, "w");
 17     fseek(temp, fileSize-1, SEEK_SET);
 18     fprintf(temp, "0"); // make the file a certain size
 19     fseek(temp, 0, SEEK_CUR);
 20 
 21     int sharedFileName = fileno(temp);
 ...
 31     sharedArea = (MyStruct*)mmap(0, fileSize,
 32         PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, sharedFileName, 0);

Io uso la modalità file "w", in quanto oggetto 1 sarà sempre e solo essere fatto una volta e voglio che per ripristinare eventuali dati preesistenti.

Codice Oggetto 2 di:

 130     FILE* tempFile = fopen(sharedFileName, "a");
 131     int theFile = fileno(tempFile);
 ...
 135     sharedArea = (MyStruct*)mmap(NULL, fileSize,
 136         PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, theFile, 0);
È stato utile?

Soluzione

A pochi problemi:

  1. Evitare di mischiare alto livello di I / O (fopen (), fseek ()) e alcune operazioni di basso livello come mmap (). Anche se è possibile ottenere il file di basso livello descrittore utilizzando fileno (), che è come prendere la strada più lunga per arrivare nello stesso posto. Inoltre, usando solo mmap () rompe la compatibilità al di là di BSD e POSIX, in modo da ottenere nulla utilizzando funzioni standard C di I / O. Basta usare open () e lseek () direttamente.
  2. Non ha senso utilizzare flusso I / O formattato (fprintf ()) sullo stesso file che sono la memoria-mapping. Quando la memoria-map di un file, si sta implicitamente dicendo al sistema che si sta per usarlo come dati ad accesso casuale (indicizzazione diretta). fprintf () è per l'uscita flusso, di solito si utilizza per l'accesso sequenziale. In realtà, anche se possibile, è raro vedere fprintf () e fseek () nello stesso descrittore (questo non è nemmeno portatile, ma a causa della voce precedente, non sto considerando la portabilità).
  3. La protezione deve corrispondere la protezione dei file aperti. Dal momento che si sta passando "w" per fopen (), e PROT_READ | PROT_WRITE | PROT_EXEC a mmap (), si stanno violando questa restrizione. Questo mette in evidenza anche il motivo per cui non si deve mescolare alto livello di I / O con la memoria-mapping: come si fa a garantire che fopen(...,"w") aprirà il file con le bandiere giuste? Questo dovrebbe essere "l'attuazione di dettagli" per la libreria C. Se si desidera la memoria-mappare un file con permessi di lettura e scrittura, si dovrebbe utilizzare il open(theSharedFileName, O_RDWR) di basso livello per aprire il file.
  4. Non l'uso PROT_WRITE e PROT_EXEC insieme. E non è portabile e si tratta di un rischio per la sicurezza. Leggi W ^ X e eseguibile protezione spazio .

Altri suggerimenti

Se è possibile utilizzare C ++ e le librerie come ACE o Boost che lo scudo dai bassi dettagli di livello e facilitare l'astrazione per IPC .

Come altri hanno detto, non utilizzare fopen () e amici di questo.

Una parte del problema riscontrato potrebbe essere dovuto al fatto che fprintf () può avere buffer di flusso, in modo che non può effettivamente cambiare il file, e quindi essere visibile per l'altro processo quando previsto. Si potrebbe aggiungere un fflush (), ma read () e write () non fare alcun buffer livello di applicazione, che fa parte del motivo per cui sono più adatti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top