首先,问题是:CLR规范是否保证在同一进程中的多个应用程序域中执行的代码将共享相同的地址空间?通过“共享地址空间”,我的意思是在其中一个应用程序域中分配的内存指针对于在同一进程内托管的所有应用程序域中进行读写都是有效的。
考虑这个自包含的示例来说明问题:程序在单独的应用程序域中分配Worker
对象。 Worker
为10,000个整数分配一个内存块,并用数据填充它。然后程序调用app域边界以获取指向已分配块的指针,并验证它是否可以读取10,000个项目中的每一个。
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace crossapp {
public class Worker : MarshalByRefObject {
private readonly IntPtr myData;
public const int DataLength = 10000;
public Worker() {
Console.Error.WriteLine(
"Memory allocation happens in app domain '{0}'"
, Assembly.GetExecutingAssembly().FullName
);
myData = Marshal.AllocHGlobal(sizeof(int) * DataLength);
unsafe {
var ptr = (int*) myData.ToPointer();
for (var i = 0 ; i != DataLength ; i++) {
ptr[i] = 2*i + 1;
}
}
}
public IntPtr GetData() {
return myData;
}
}
class Program {
static void Main() {
var ad = AppDomain.CreateDomain("New domain");
var wrk = (Worker)ad.CreateInstanceAndUnwrap(
Assembly.GetExecutingAssembly().FullName
, "crossapp.Worker"
);
var data = wrk.GetData();
var badCount = 0;
unsafe {
var ptr = (int*)data.ToPointer();
for (var i = 0 ; i != Worker.DataLength ; i++) {
var expect = 2*i + 1;
if (ptr[i] != expect) {
Console.Error.WriteLine(
"Mismatch in position {0}: {1} != {2}"
, i, expect, ptr[i]
);
badCount++;
}
}
if (badCount == 0) {
Console.Error.WriteLine(
"All {0} items have matched."
, Worker.DataLength
);
} else {
Console.Error.WriteLine(
"Found {0} mismatches out of {1}."
, badCount
, Worker.DataLength
);
}
}
}
}
}
我跑了很多次,每次都有效。直觉上它应该工作:毕竟,应用程序域在一个进程内,因此它们必须共享相同的虚拟地址空间。但是,这感觉就像微软可能随时带走的功能一样。 CLR规范中是否有某些内容证实或否认了这一技巧的合法性?
<小时/> 如果你想知道为什么我问这么奇怪的问题,我正在寻找一种在app域边界传递大量(以千兆字节为单位)数据的方法,同时在空间和时间上的开销最小。如果我能证明它的合法性,这将是我理想的解决方案。
答案 0 :(得分:1)
看看:Anyone can explain the major use of MarshalByRefObject。 在您的方案中,您只传递代理而不是实际对象,并且未复制内存。
编辑:
答案 1 :(得分:-1)
我没有直接的回答。 MarshalByRefObject的存在可能表明使用了公共地址空间,但可能没有。
您也可以查看memory-mapped files