0

我正在尝试将 Isis2 库的新版本从 Windows 上的 .NET 移植到 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 对象有经验吗?我在这里和其他网站上看到很多关于此类问题的问题,但似乎都是旧线程......

4

1 回答 1

3

好的,通过检查实现此 API 的 Mono 代码,我至少发现了其中的一部分。事实上,他们实现 CreateNew 的方式与 .NET API 大相径庭,导致这些方法的行为与您所期望的非常不同。

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

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

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

至于我的链接问题,据我所知,有一种情况是 Mono 没有使用您正确指定的 LD_LIBRARY_PATH ,因此找不到您使用的 .so 文件或 .dll 文件。如果我能准确地确定情况,我将在此发布更多信息——在这个问题上,我通过静态链接到库来解决这个问题。

于 2013-08-15T17:46:51.900 回答