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);
Soluzione
A pochi problemi:
- 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.
- 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à).
- 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 chefopen(...,"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 ilopen(theSharedFileName, O_RDWR)
di basso livello per aprire il file. - Non l'uso
PROT_WRITE
ePROT_EXEC
insieme. E non è portabile e si tratta di un rischio per la sicurezza. Leggi W ^ X e eseguibile protezione spazio .
Altri suggerimenti
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.