2010-01-05 27 views
16

No encuentro ninguna respuesta útil para esta pregunta, aunque se ha preguntado de manera diferente varias veces.Memoria compartida entre 2 procesos (aplicaciones)

Quiero compartir una memoria entre dos procesos (dos aplicaciones diferentes), para que uno de ellos pueda escribir en esa memoria y el otro pueda leer.

¿Esto es posible en .NET? ¿Cómo?

Gracias

+0

duplicado: http://stackoverflow.com/questions/439787/how-to-implement-shared-memory-in-net –

+0

pero no hay una buena respuesta en esa pregunta duplicada también –

+0

Hay buenas respuestas en la pregunta duplicada. Simplemente no les gusta lo que dicen. Pero no hay una forma integrada de compartir memoria en .NET, puede usar P-Invoke o probar con otro IPC. – Niki

Respuesta

29

En este momento, .NET no admite secciones (también conocido como archivos asignados de memoria). Pronto, la versión 4.0 tiene el espacio de nombres System.IO.MemoryMappedFiles. Hay una buena razón por la que tomó tanto tiempo y también la razón por la que no estará contento con esta adición. El uso de punteros es obligatorio en los archivos MMF, la memoria compartida está disponible en una dirección específica. Para compartir un valor, deberá escribirlo en una dirección específica.

Sin embargo, los punteros son fundamentalmente incompatibles con el modelo de memoria administrada. Los objetos se crean en un montón recogido de basura, el recolector los mueve según sea necesario para mantener el montón compactado. En un lenguaje administrado, tiene una referencia a dicho objeto, también conocido como un "identificador de seguimiento". El equivalente de C/C++ es un puntero, pero es uno con campanas encendidas, el recolector de basura siempre puede encontrarlo y actualizar su valor. El CLR admite la noción de "fijación", convierte una referencia a un puntero. Implementa esto al marcar el objeto como inamovible. Sin embargo, eso no ayuda a implementar la memoria compartida a través de un archivo MMF, el objeto está anclado en el montón de GC en lugar de la dirección de memoria virtual donde se encuentra la vista de MMF.

Para hacer que un archivo MMF funcione, el objeto debe copiarse del montón del GC a la memoria compartida. Eso requiere serialización. La clase .NET 4.0 se llama MemoryMappedViewStream.Es probable que pueda ver a dónde va esto, esto es indistinguible de usar una tubería con nombre o un zócalo. Obtener datos dentro y fuera de un archivo MMF requiere el mismo esfuerzo. Un MMF es simplemente un poco más eficiente porque el búfer subyacente no está en el grupo de memoria del kernel.

Puede romper las reglas y hacerlo hoy. Puede P/Invocar CreateFileMapping, OpenFileMapping y MapViewOfFile que necesita para crear un archivo MMF. Y use la palabra clave insegura para que pueda crear punteros. Tendrá que usar tipos de valor (como struct) para los elementos de memoria compartida o usar la clase Marshal.

+2

Estás asumiendo que "compartir datos" debe significar compartir objetos administrados directamente. ¿Qué pasa si alguien quiere compartir algunos datos "simples"? – devdimi

+0

No estoy seguro de qué significa "simple". Pero aún no puede afectar la dirección de los tipos de valor directamente, ellos viven en la pila o en el montón de GC. Se requiere un puntero para que se escriban en un archivo MMF. –

+1

Creo que con datos simples, quiere decir simplemente un montón de bytes que descifrar usted mismo, solo quiere escribir el código para leer/escribir el archivo de memoria asignado – BlueTrin

1

Utilice un named pipe.

Es un mecanismo que permite que un proceso escriba datos secuenciales en una secuencia, desde la cual puede leer el otro proceso.

Tenga en cuenta que la tubería con nombre solo permite lectura secuencial. Si necesita utilizar consultas más elaboradas, quizás desee utilizar la arquitectura cliente-servidor. En este caso, el proceso de lectura consulta el otro proceso para obtener información usando network sockets.

+0

No quiero utilizar canalizaciones con nombre, WCF, remotas ... etc ... es por eso que especifiqué "memoria compartida", la memoria compartida entre 2 aplicaciones es fácil de establecer en C++, pero no puedo encontrar la manera de hazlo en C# .net –

+0

No he visto ninguna implementación directa de la memoria compartida, pero puedes implementar fácilmente un tercer proceso que manejaría las lecturas y escrituras de ambos procesos usando sockets. –

+1

Creo que todos están perdiendo el sentido. Compartir la memoria es fundamentalmente diferente de la sincronización de objetos a través de cualquier mecanismo. Con la memoria compartida, hay un estado constante compartido entre los procesos. Con pipes/wcf/etc, hay un proceso de (de) serialización/transmisión que es caro en términos de ciclos. La memoria compartida se usa cuando quiere que un proceso manipule un objeto en otro directamente (digamos cómo Chrome tiene múltiples procesos que se procesan en la misma ventana. Es mucho más barato dibujar directamente que serializar un mapa de bits una y otra vez) – Basic

4

IPC

Si usted está hablando de Comunicación Inter proceso. Hay varias posibilidades como el uso de sockets TCP/UDP, procesadores de mensajes, canalizaciones con nombre, la memoria de archivos, mensajes de ventanas, etc. asignan

Net también ofrece algún nivel más alto IPC como .Net remoting y WCF que utilizan las técnicas mencionadas anteriores. Puede leer más al respecto here.

archivos de memoria asignada

Si realmente desea compartir un bloque de memoria en lugar de la comunicación, entonces tal vez asignada la memoria archivos son los deseados. .Net 4.0 tiene MemoryMappedFile para eso. Si no usa .Net 4.0 o no puede hacerlo, puede implementarlo usted mismo como en este win32 example. O puede probar el código this o ver si puede usar MemoryMappedFileStream mencionado here y here. O use esta clase FileMap.

+0

No quiero usar pipes nombrados, WCF, remoting ... etc ... es por eso que especifiqué "memoria compartida", la memoria compartida entre 2 aplicaciones es fácil de establecer en C++, pero no puedo encontrar la manera de hacerlo en C# .net Estoy usando .NET 2.0, ¿hay alguna forma de solucionarlo? No quiero irme de terceros. –

+0

Actualicé mi respuesta con más información –

0

Como ya se mencionó, use Archivos de memoria asignados. Implementación para .NET < 4 disponible en: http://github.com/tomasr/filemap/
Lo he usado y funciona sin defectos. Puede tener algunos problemas de seguridad cuando se comparte entre procesos elevados/no elevados: la solución es inicializar el archivo mapeado en memoria en el proceso elevado y configurar sus atributos de seguridad en consecuencia.

Cuestiones relacionadas