AppDomain地址空间 [英] AppDomain address space

查看:21
本文介绍了AppDomain地址空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,问题是:CLR 规范是否保证在同一进程内的多个应用程序域中执行的代码将共享相同的地址空间?共享地址空间"是指指向在一个应用程序域中分配的内存的指针对于在同一进程内托管的所有应用程序域之间进行读写是有效的.

First, the question: do CLR specifications guarantee that the code executing in multiple app domains within the same process will share the same address space? By "sharing the address space" I mean that pointers to memory allocated in one of the app domains will be valid for reading and writing across all app domains hosted inside the same process.

考虑这个说明问题的独立示例:程序在单独的应用程序域中分配一个 Worker 对象.Worker 为 10,000 个整数分配一个内存块,并用数据填充它.然后程序跨应用域边界调用以获取指向分配块的指针,并验证它可以读取 10,000 个项目中的每一个.

Consider this self-contained example illustrating the question: the program allocates a Worker object in a separate app domain. The Worker allocates a memory block for 10,000 integers, and fills it in with data. The program then calls across the app domain boundary to obtain the pointer to the allocated block, and verifies that it can read every one of the 10,000 items.

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
                    );
                }
            }
        }
    }
}

我运行了很多次,每次都有效.直观上它应该可以工作:毕竟,应用程序域在单个进程中,因此它们必须共享相同的虚拟地址空间.但是,这感觉像是对 Microsoft 可能随时删除的功能的一种利用.CLR 的规范中是否有确认或否认此技巧合法性的内容?


如果您想知道为什么我问这样一个奇怪的问题,我正在寻找一种方法来跨应用程序域边界传递大量(以千兆字节为单位)数据,同时在空间和时间上的开销最小.如果我能证明其合法性,这将是我理想的解决方案.

I ran this many times, and it worked every single time. Intuitively it should work: after all, app domains are within a single process, so they must share the same virtual address space. However, this feels like an exploit of a feature that Microsoft may take away at any time. Is there something in the specification of CLR that confirms or denies legitimacy of this trick?


In case you are wondering why I am asking such a strange question, I am looking for a way of passing large (in gigabytes) amounts of data across app domain boundary, with minimal overhead in both space and time. This would be my ideal solution if I could prove its legitimacy.

推荐答案

看:任何人都可以解释 MarshalByRefObject 的主要用途.在您的场景中,您只传递代理而不是实际对象,并且不会复制内存.

Look at: Anyone can explain the major use of MarshalByRefObject . In your scenario, you are only passing a proxy and not the actual object and the memory is not being copied.


  1. "合法性" != "trick",您的黑客行为通过不封送对另一个 AppDomain 中的数据的调用来破坏 AppDomain.运行时容器可能会设置/更改可能会破坏您的应用程序的安全限制,例如这是在 IIS 内运行吗?(就您而言,您访问的不是对象而是内存,因此可能还不错".)这是您在客户站点部署的产品吗?
  2. 我认为通过代理进行编组存在性能问题,因此您求助于 IntPtr(去掉中间人)
  3. 各种工人"AppDomain 是否在操纵 blob?如果是这样,我会担心最终内存会被破坏......因为你没有编组你的电话.
  4. 这是在 C# 中创建的非托管内存.如果实际上 blob 是由非托管 DLL 分配的,则必须确保未卸载非托管 DLL.同样,如果要部署到 IIS,则您无法控制 AppDomains 的生命周期,而 IIS 可以.这会破坏你的黑客行为.
  5. 是的,虚拟内存是针对每个进程的,而不是针对每个 AppDomain 的,因此所有 AppDomain 共享相同的虚拟地址空间.
  6. 不管我有没有保留,这都非常酷:)

这篇关于AppDomain地址空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆