代码之家  ›  专栏  ›  技术社区  ›  foobarfuzzbizz

对文件使用mmap

  •  4
  • foobarfuzzbizz  · 技术社区  · 15 年前

    我试图通过使用内存映射同一个文件来允许两个不同的进程进行通信。但是,我有一些问题。我觉得这与我使用open()调用并将文件描述符传递给mmap的方式有关。

    这是我的密码,你看出来有什么问题吗?

    对象1的代码:

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

    我使用“w”文件模式,因为对象1只生成一次,我希望它重置任何以前存在的数据。

    对象2的代码:

     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);
    
    3 回复  |  直到 15 年前
        1
  •  24
  •   Juliano    15 年前

    几个问题:

    1. 避免混合使用高级I/O(fopen(),fseek())和一些低级操作(如mmap())。尽管可以使用fileno()获得低级文件描述符,但这就像是走最长的路径到达同一个位置。另外,仅仅使用mmap()就打破了bsd和posix之外的兼容性,因此使用标准c i/o函数什么也得不到。直接使用open()和lseek()即可。
    2. 在内存映射的同一个文件上使用流格式的I/O(fprintf())是没有意义的。当内存映射文件时,您将隐式地告诉系统您要将其用作随机访问(直接索引)数据。fprintf()用于流输出,通常用于顺序访问。实际上,虽然可能,但是在同一个描述符中看到fprintf()和fseek()是不寻常的(这甚至不是可移植的,但是由于前面的项目,我不考虑可移植性)。
    3. 保护必须与打开的文件保护匹配。因为您将“w”传递给fopen(),并且 PROT_READ | PROT_WRITE | PROT_EXEC 对于mmap(),您违反了此限制。这也突出了为什么不应该将高级I/O与内存映射混合在一起:如何保证 fopen(...,"w") 将用正确的标志打开文件吗?这应该是C库的“实现细节”。如果您希望内存映射具有读写权限的文件,则应使用低级别 open(theSharedFileName, O_RDWR) 打开文件。
    4. 使用 PROT_WRITE PROT_EXEC 一起。它不可携带 这是一种安全风险。阅读有关 W^X executable space protection .
        2
  •  2
  •   lothar    15 年前

    如果你可以使用C++和类库 ACE Boost 它可以保护您不受底层细节的影响,并为 IPC .

        3
  •  1
  •   Don Neufeld    15 年前

    正如其他人所说,不要使用fopen()和friends。

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