Адресное пространство 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 может указывать на то, что используется общее адресное пространство, но, возможно, нет.
Вы также можете посмотреть файлы с отображением памяти