AppDomain地址空间

时间:2012-08-20 20:28:19

标签: .net memory pointers appdomain address-space

首先,问题是: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域边界传递大量(以千兆字节为单位)数据的方法,同时在空间和时间上的开销最小。如果我能证明它的合法性,这将是我理想的解决方案。

2 个答案:

答案 0 :(得分:1)

看看:Anyone can explain the major use of MarshalByRefObject。 在您的方案中,您只传递代理而不是实际对象,并且未复制内存。

编辑:

  1. &#34;合法性&#34; !=&#34;技巧&#34;,你的黑客正在通过不对另一个AppDomain中的数据进行封送来破坏AppDomains。运行时容器可能会设置/更改可能会破坏您应用的安全限制,例如:这是在IIS内部运行? (在您的情况下,您不是访问对象而是访问内存,因此它可能是&#34;不是那么糟糕&#34;。)这是您在客户网站上部署的产品吗?
  2. 我认为通过代理编组存在性能问题,所以你使用了IntPtr(剪掉了中间人)
  3. 各种各样的&#34;工人&#34; AppDomains操纵blob?如果是这样,我会担心最终内存会被破坏......因为你没有整理你的电话。
  4. 这是在C#中创建的非托管内存。如果实际上,blob是由非托管DLL分配的,那么您必须确保未卸载非托管DLL。同样,如果要部署到IIS,那么您无法控制您的AppDomains&#39;生命周期,IIS确实如此。这将打破你的黑客。
  5. 是的,虚拟内存是按进程而不是每个AppDomain,因此所有AppDomain共享相同的虚拟地址空间。
  6. 无论我的保留意见如何,都很酷:)

答案 1 :(得分:-1)

我没有直接的回答。 MarshalByRefObject的存在可能表明使用了公共地址空间,但可能没有。

您也可以查看memory-mapped files