Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using mmap over a file

Tags:

c

file

mmap

I'm trying to allow two different processes to communicate by using memory mapping the same file. However, I'm having some problems with this. I have a feeling this has to do with the way I'm using the open() call and passing my file descriptor to mmap.

Here is my code, can you see anything wrong with it?

Object 1's code:

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

I use the "w" file mode since Object 1 will only ever be made once and I want it to reset any previously existing data.

Object 2's Code:

 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);
like image 487
samoz Avatar asked Nov 28 '22 13:11

samoz


1 Answers

A few issues:

  1. Avoid mixing high-level I/O (fopen(), fseek()) and some low-level operation like mmap(). Although you can get the low-level file descriptor using fileno(), that is like taking the longest route to get to the same place. Also, just using mmap() breaks compatibility beyond BSD and POSIX, so you get nothing by using standard C I/O functions. Just use open() and lseek() directly.
  2. It doesn't make sense to use stream formatted I/O (fprintf()) on the same file you are memory-mapping. When you memory-map a file, you are implicitly telling the system you are going to use it as random-access (direct indexing) data. fprintf() is for stream output, you usually use it for sequential access. In fact, although possible, it is unusual to see fprintf() and fseek() in the same descriptor (this is not even portable, but due to the previous item, I'm not considering portability).
  3. The protection must match the open file protection. Since you are passing "w" to fopen(), and PROT_READ | PROT_WRITE | PROT_EXEC to mmap(), you are violating this restriction. This also highlights why you shouldn't mix high-level I/O with memory-mapping: how do you guarantee that fopen(...,"w") will open the file with the correct flags? This is supposed to be "implementation-detail" for the C library. If you want to memory-map a file with read and write permissions, you should use the low-level open(theSharedFileName, O_RDWR) to open the file.
  4. Do not use PROT_WRITE and PROT_EXEC together. It is not portable and it is a security risk. Read about W^X and executable space protection.
like image 127
Juliano Avatar answered Dec 04 '22 23:12

Juliano