4

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

3 回答 3

25

几个问题:

  1. 避免混合高级 I/O(fopen()、fseek())和一些低级操作,如 mmap()。虽然您可以使用 fileno() 获取低级文件描述符,但这就像走最长的路线到达同一个地方。此外,仅使用 mmap() 会破坏 BSD 和 POSIX 之外的兼容性,因此使用标准 CI/O 函数将一无所获。直接使用 open() 和 lseek() 即可。
  2. 在内存映射的同一个文件上使用流格式的 I/O (fprintf()) 是没有意义的。当您对文件进行内存映射时,您隐含地告诉系统您将使用它作为随机访问(直接索引)数据。fprintf() 用于流输出,通常用于顺序访问。事实上,尽管可能,但在同一个描述符中看到 fprintf() 和 fseek() 是不寻常的(这甚至是不可移植的,但由于前一项,我不考虑可移植性)。
  3. 保护必须与打开文件保护相匹配。由于您将“w”传递给 fopen() 和PROT_READ | PROT_WRITE | PROT_EXECmmap(),因此您违反了此限制。这也突出了为什么您不应该将高级 I/O 与内存映射混合使用:您如何保证fopen(...,"w")将使用正确的标志打开文件?这应该是 C 库的“实现细节”。如果要对具有读写权限的文件进行内存映射,则应使用低级别open(theSharedFileName, O_RDWR)打开该文件。
  4. 不要PROT_WRITEPROT_EXEC一起使用。它不可移植存在安全风险。阅读有关W^X可执行空间保护的信息。
于 2009-04-12T23:32:01.063 回答
2

如果您可以使用 C++ 和诸如ACEBoost之类的库来保护您免受底层细节的影响,并为IPC提供更容易的抽象。

于 2009-04-13T01:31:01.637 回答
2

正如其他人所说,不要为此使用 fopen() 和朋友。

您遇到的部分问题可能是由于 fprintf() 可以具有流缓冲区,因此它实际上可能不会更改文件,因此在预期时对其他进程可见。您可以添加一个 fflush(),但 read() 和 write() 不执行任何应用程序级缓冲,这也是它们更适合的部分原因。

于 2009-04-13T00:03:03.360 回答