在Mono上使用MemoryMappedFile类的问题

时间:2013-08-14 19:25:50

标签: c#-4.0 mono memory-mapped-files

我正在尝试将Windows上的.NET的Isis2库的新版本移植到Mono / Linux。这个新代码使用了MemoryMappedFile对象,我突然遇到了Mono.Posix.Helper库的问题。我相信如果我能成功编译并运行以下测试程序,我的问题就会消失:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.MemoryMappedFiles;

namespace foobar
{
  class Program
  {
    static int CAPACITY = 100000;
    static void Main(string[] args)
    {
        MemoryMappedFile mmf = MemoryMappedFile.CreateNew("test", CAPACITY);
        MemoryMappedViewAccessor mva = mmf.CreateViewAccessor();
        for (int n = 0; n < CAPACITY; n++)
        {
            byte b = (byte)(n & 0xFF);
            mva.Write<byte>(n, ref b);
        }
    }
  }
}

...目前,当我尝试在Mono上编译它时,我得到一组令人眼花缭乱的链接器错误:它似乎无法找到libMonoPosixHelper.so,虽然我的LD_LIBRARY_PATH包含包含该文件的目录,然后如果我管理为了超越那个阶段,我得到“System.NotImplementedException:未实现所请求的功能。”在运行时。然而,我已经看过了CreateNew方法的Mono实现;它似乎完全实现了,CreateViewAccessor方法也是如此。因此,我感觉链接到Mono库时出现了严重错误。

有没有人有使用Mono下的MemoryMappedFile对象的经验?我在这里和其他网站上看到了很多关于这类问题的问题,但似乎都是老问题......

1 个答案:

答案 0 :(得分:2)

好的,通过检查实现此API的Mono代码,我至少想到了部分内容。事实上,他们以一种与.NET API非常不同的方式实现了CreateNew,导致这些方法的行为与您期望的非常不同。

对于CreateNew,他们实际上要求您指定的文件名是现有Linux文件的名称,其大小至少与您指定的容量一样大,并且还要对访问权限进行一些其他检查(当然),独占访问(与共享...不一致)并确保您请求的容量是&gt;因此,如果您以前打开过该文件,或者其他人这样做,那么这将失败 - 与.NET相比,您明确使用内存映射文件进行共享。

相比之下,CreateOrOpen似乎“或多或少”正确实现;切换到这个版本似乎解决了这个问题。要获得CreateNew的效果,首先执行Delete,将其包装在try / catch中以捕获IOException(如果该文件不存在)。然后使用File.WriteAllBytes创建包含所需内容的文件。然后调用CreateOrOpen。现在这听起来很愚蠢,但它确实有效。显然你不能用这种方式保证原子性(三个操作而不是一个),但至少你得到了所需的功能。

我可以忍受这些限制,但它们可能会让其他人感到惊讶,并且与MemoryMappedFile的.NET API定义完全不同。

至于我的链接问题,据我所知,有一种情况,Mono没有使用你正确指定的LD_LIBRARY_PATH,因此无法找到你使用的.so文件或.dll文件。如果我可以准确地确定情况,我会在此发布更多内容 - 在这一点上,我通过静态链接到库来解决这个问题。