我正在尝试将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对象的经验吗?我在这里和其他网站上看到了相当多关于这类问题的问题,但似乎都是老帖子……
发布于 2013-08-16 01:46:52
好的,通过检查实现此API的Mono代码,我至少了解了其中的一部分。事实上,他们实现CreateNew的方式与.NET应用程序接口截然不同,导致这些方法的行为与您预期的截然不同。
对于CreateNew,它们实际上要求您指定的文件名是一个现有Linux文件的名称,大小至少与您指定的容量一样大,并且还对访问权限(当然)、独占访问(这与共享不一致……)进行一些其他检查。并确保您请求的容量> 0。因此,如果您之前打开了该文件,或者其他人打开了该文件,则此操作将失败--这与显式使用内存映射文件进行共享的.NET相反。
相比之下,CreateOrOpen似乎“或多或少”被正确地实现了;切换到这个版本似乎可以解决问题。要获得CreateNew的效果,请先执行删除操作,如果文件不存在,则将其包装在IOException / catch中以捕获该文件。然后使用File.WriteAllBytes创建包含所需内容的文件。然后调用CreateOrOpen。现在这听起来很愚蠢,但它是有效的。显然,您不能以这种方式保证原子性(三个操作而不是一个),但至少您获得了所需的功能。
我可以接受这些限制,但它们可能会让其他人感到惊讶,并且与MemoryMappedFile的.NET应用编程接口定义完全不同。
至于我的链接问题,据我所知,有一种情况是Mono没有正确使用您指定的LD_LIBRARY_PATH,因此找不到您使用的.so文件或.dll文件。如果我能准确地确定情况,我将发表更多关于这个问题的文章--在这个问题上,我已经通过静态链接到库来解决了这个问题。
https://stackoverflow.com/questions/18240535
复制相似问题