.net - Espacio de direcciones de AppDomain




memory pointers (2)

Primero, la pregunta: ¿las especificaciones de CLR garantizan que el código que se ejecuta en múltiples dominios de aplicaciones dentro del mismo proceso compartirá el mismo espacio de direcciones? Al "compartir el espacio de direcciones" quiero decir que los punteros a la memoria asignada en uno de los dominios de la aplicación serán válidos para leer y escribir en todos los dominios de la aplicación alojados dentro del mismo proceso.

Considere este ejemplo autónomo que ilustra la pregunta: el programa asigna un objeto Worker en un dominio de aplicación separado. El Worker asigna un bloque de memoria para 10.000 enteros y lo llena con datos. El programa llama a través del límite del dominio de la aplicación para obtener el puntero al bloque asignado y verifica que puede leer cada uno de los 10 000 elementos.

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

Corrí esto muchas veces, y funcionó todas las veces. Intuitivamente debería funcionar: después de todo, los dominios de la aplicación se encuentran dentro de un único proceso, por lo que deben compartir el mismo espacio de direcciones virtuales. Sin embargo, esto parece una explotación de una característica que Microsoft puede quitar en cualquier momento. ¿Hay algo en la especificación de CLR que confirme o niegue la legitimidad de este truco?

En caso de que se esté preguntando por qué estoy haciendo una pregunta tan extraña, estoy buscando una forma de pasar cantidades de datos grandes (en gigabytes) a través del límite del dominio de la aplicación, con una sobrecarga mínima tanto en espacio como en tiempo. Esta sería mi solución ideal si pudiera probar su legitimidad.


No tengo una respuesta directa para ti. La existencia de MarshalByRefObject podría indicar que se usa un espacio de direcciones común, pero quizás no.

También puede buscar en archivos mapeados en memoria


Mira: Cualquiera puede explicar el uso principal de MarshalByRefObject . En su escenario, solo está pasando un proxy y no el objeto real y la memoria no se está copiando.

EDITAR:

  1. "legitimidad"! = "truco", su pirateo está minando AppDomains al no coordinar llamadas a datos en otro AppDomain. El contenedor de tiempo de ejecución puede establecer / cambiar las limitaciones de seguridad que pueden romper su aplicación, por ejemplo, ¿se está ejecutando dentro de IIS? (En su caso, no está accediendo a un objeto sino a la memoria, por lo que tal vez "no sea tan malo"). ¿Es este un producto que está implementando en el sitio de un cliente?
  2. Supongo que hubo un problema de rendimiento con la clasificación por proxy, por lo que recurrió a IntPtr (cortar el intermediario)
  3. ¿Los diversos AppDomains "trabajadores" manipulan el blob? Si es así, me preocuparía que eventualmente la memoria se corrompiera ... porque no estás coordinando tus llamadas.
  4. Esta es una memoria no administrada creada en C #. Si en realidad, el blob es asignado por una DLL no administrada, entonces debe asegurarse de que la DLL no administrada no se descargue. De nuevo, si se está implementando en IIS, entonces no controla los ciclos de vida de sus AppDomains, IIS sí lo hace. Esto romperá tu hack.
  5. Sí, la memoria virtual es por proceso y no por Dominio de aplicación, por lo que todos los dominios de aplicación comparten el mismo espacio de direcciones virtuales.
  6. Independientemente de mis reservas, es genial :)




address-space