2010-12-04 13 views
7

Tengo una clase muy complicada (tiene unordered_map y así sucesivamente) y quiero compartir un objeto con dos de mis procesos. ¿Puedo simplemente pasarle un puntero de un proceso a otro? Creo que no, pero espero escuchar "¡Sí!".¿Puedo pasar un objeto a otro proceso simplemente pasando su puntero a una memoria compartida?

Si la respuesta es "no", le agradecería ver algún enlace sobre cómo hacer frente a estos casos. Necesito tener solo una instancia de este objeto para todos los procesos porque es muy grande y todos los procesos funcionarán solo para lectura.

+1

@si tiene control sobre estos procesos, ¿por qué no convertirlos en hilos? Compartir la memoria es más fácil que Parece más sensato ya que todos tendrán un conocimiento adecuado de sus estructuras de datos internas (usted compartió el objeto) – Toad

+0

Sí, creo que seguiré por este camino. Y le hice la pregunta para asegurarme de que no tengo una solución fácil con IPC. – flashnik

Respuesta

4

No, proceso no (naturalmente) memoria compartida. Si el impulso es una opción, entonces puede echarle un vistazo al Boost.Interprocess para compartir fácilmente la memoria.

2

No, el puntero no tiene sentido para el otro proceso. El sistema operativo crea un espacio de direcciones separado para otros procesos; de forma predeterminada, no tienen idea de que se están ejecutando otros procesos, o incluso que tal cosa es posible.

+0

Es una respuesta para la que estaba preparado pero esperaba que pudiera haber algún truco :( – flashnik

0

El truco aquí es que la memoria debe ser asignada de la misma manera en ambos procesos. Si su memoria compartida mapeada puede organizarse de esa manera, funcionará, pero apuesto a que será muy difícil.

Hay un par de otras posibilidades. El primero es usar una matriz; los índices de matriz serán trabajando en ambos procesos.

También puede usar placement new para asegurarse de que está asignando objetos en una ubicación conocida dentro de la memoria compartida, y usar esos desplazamientos.

0

Si está en Linux, puede usar la memoria compartida para almacenar datos comunes entre procesos. Para el caso general, eche un vistazo a la biblioteca de impulso de IPC.

Pero puntero de un proceso no puede ser utilizado en otro (que es la dirección se pueden utilizar, si se accede a IO, o algunos dispositivos especiales)

0

Si utiliza Qt4 hay QSharedMemory o usted podría utilizar sockets y una serialización personalizada protocolo.

10

Ciertamente puede usar IPC para lograr esto, y hay muchos casos en que múltiples procesos tienen más sentido que un proceso multiproceso (al menos uno de los procesos se basa en código heredado al que no se pueden realizar modificaciones , que mejor serían escritos en diferentes idiomas, es necesario minimizar la posibilidad de errores en un proceso que afecta a la estabilidad de los demás, etc.) en un entorno compatible con POSIX, que haría

int descriptor = shm_open("/unique_name_here", O_RDWR | O_CREAT, 0777); 

if (descriptor < 0) { 
    /* handle error */ 
} else { 

    ftruncate(descriptor, sizeof(Object)); 
    void *ptr = mmap(NULL, sizeof(Object), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, descriptor, 0); 

    if (!ptr || ptr == MAP_FAILED) 
     /* handle error */ ; 

    Object *obj = new (ptr) Object(arguments); 
} 

en una proceso, y luego

int descriptor = shm_open("/the_same_name_here", O_RDWR | O_CREAT, 0777); 

if (descriptor < 0) { 
    /* handle error */ 
} else { 

    Object *obj = (Object *) mmap(NULL, sizeof(Object), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, descriptor, 0); 

    if (!obj || obj == MAP_FAILED) 
     /* handle error */ ; 
} 

en el otro. Hay muchas más opciones, y no mostré el código de limpieza cuando terminaste, por lo que todavía deberías leer las páginas de manual de shm_open() y mmap(), pero esto debería ayudarte a comenzar. Algunas cosas para recordar:

  • /Toda la memoria que el objeto utiliza necesita ser compartida. Por ejemplo, si el objeto contiene punteros o referencias a otros objetos, o miembros dinámicamente asignados (incluyendo cosas como contenedores, std :: string, etc.), tendrá que usar la colocación nueva para crear todo (o al menos todo lo que necesita ser compartido con los otros procesos) dentro del blob de memoria compartida.No necesita un nuevo shm_open() para cada objeto, pero sí tiene que hacer un seguimiento (en el proceso de creación) de sus tamaños y desplazamientos, que pueden ser propensos a errores en casos no triviales y absolutamente tirando del pelo si tiene sofisticados tipos de autoasignación como contenedores STL.

  • Si algún proceso modificará el objeto después de haber sido compartido, deberá proporcionar un mecanismo de sincronización por separado. Esto no es peor que lo que harías en un programa multiproceso, pero tienes que pensarlo.

  • Si los procesos 'cliente' no necesitan modificar el objeto compartido, debería abrir sus identificadores con O_RDONLY en lugar de O_RDWR e invocar mmap() sin el indicador de permiso PROT_WRITE. Si los procesos del cliente pueden hacer modificaciones locales que no necesitan compartirse con los otros procesos, invoque mmap() con MAP_PRIVATE en lugar de MAP_SHARED. Esto reducirá en gran medida la cantidad de sincronización requerida y los riesgos de atornillarla.

  • Si estos procesos se ejecutarán en un sistema multiusuario y/o los datos compartidos pueden ser sensibles y/o esta es una aplicación de alta disponibilidad, querrá un control de acceso más sofisticado que el mostrado anteriormente . La memoria compartida es una fuente común de agujeros de seguridad.

+0

Si construyo un objeto con un nuevo operador de ubicación, ¿construirá automáticamente sus 'miembros con el mismo operador? – flashnik

+0

Los miembros que no sean punteros serán, por supuesto, construido dentro del espacio asignado al objeto padre. Si los constructores de su clase u otros métodos usan nuevo para asignar espacio para otros objetos, esa memoria no/estará dentro de la burbuja compartida. Como se señaló en la primera viñeta, esta puede ser una de las principales fuente de complejidad y errores. Si sus objetos compartidos son demasiado complejos para evitar manualmente este comportamiento, podría considerar la definición de un nuevo operador personalizado que asigna dentro del blob cuando se establece un indicador global particular. – spillner

Cuestiones relacionadas