Адресное пространство AppDomain

Во-первых, вопрос: выполняют ли спецификации CLR, что код, выполняемый в нескольких доменах приложения в одном и том же процессе, будет иметь одно и то же адресное пространство? "Совместное использование адресного пространства" означает, что указатели на память, выделенные в одном из доменов приложений, будут действительны для чтения и записи во всех доменах приложений, размещенных внутри одного процесса.

Рассмотрим этот самодостаточный пример, иллюстрирующий вопрос: программа выделяет объект Worker в отдельном домене приложения. Worker выделяет блок памяти для 10 000 целых чисел и заполняет его данными. Затем программа перебирает границу домена приложения, чтобы получить указатель на выделенный блок, и проверяет, что он может читать каждый из 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
                    );
                }
            }
        }
    }
}

Я работал много раз, и он работал каждый раз. Интуитивно он должен работать: ведь домены приложений находятся в рамках одного процесса, поэтому они должны совместно использовать одно и то же виртуальное адресное пространство. Однако это похоже на использование функции, которую Microsoft может отнять в любой момент. Есть ли что-то в спецификации CLR, которая подтверждает или отрицает легитимность этого трюка?


В случае, если вам интересно, почему я задаю такой странный вопрос, я ищу способ передачи больших (в гигабайтах) объемов данных через границу домена приложения с минимальными накладными расходами как в пространстве, так и во времени. Это было бы идеальным решением, если бы я мог доказать свою легитимность.

Ответы

Ответ 1

Посмотрите: Любой может объяснить основное использование MarshalByRefObject. В вашем сценарии вы передаете прокси, а не фактический объект, и память не копируется.

EDIT:

  • "легитимность"!= "трюк", ваш взлом подрывает AppDomains, не маршируя вызовы с данными в другой AppDomain. Контейнер времени выполнения может устанавливать/изменять ограничения безопасности, которые могут нарушить ваше приложение, например. это работает внутри IIS? (В вашем случае вы не получаете доступ к объекту, кроме памяти, поэтому, возможно, это "не так уж плохо".) Является ли это продуктом, который вы развертываете на сайте клиента?
  • Я предполагаю, что возникла проблема с маршалингом через прокси-сервер, поэтому вы прибегли к IntPtr (вырезали среднего человека).
  • Являются ли различные "рабочие" AppDomains манипулированием блобом? Если это так, я буду обеспокоен тем, что в конечном итоге память будет повреждена... потому что вы не маршируете свои звонки.
  • Это неуправляемая память, созданная на С#. Если на самом деле, blob выделяется неуправляемой DLL, тогда вы должны убедиться, что неуправляемая DLL не выгружена. Опять же, если они развертываются в IIS, то вы не контролируете жизненные циклы AppDomains, IIS. Это сломает ваш взлом.
  • Да, виртуальная память предназначена для каждого процесса, а не для AppDomain, поэтому все AppDomain используют одно и то же виртуальное адресное пространство.
  • Независимо от моих оговорок, это очень круто:)

Ответ 2

У меня нет прямого ответа для вас. Существование MarshalByRefObject может указывать на то, что используется общее адресное пространство, но, возможно, нет.

Вы также можете посмотреть файлы с отображением памяти