Estoy revisando un programa escrito en C / C ++ para control en robótica. Básicamente, tres programas diferentes se ejecutan al mismo tiempo y se comunican a través de la memoria compartida. Google-ling alrededor que encontré piensa como vxWorks y los encabezados de interproceso de bibliotecas de impulso ( documentación de Boost: compartir memoria entre procesos ).
Ahora, no quiero ver la implementación, puedo leer el enlace de arriba. Pero no puedo entender cómo la biblioteca de impulso hace esto. Quiero decir, una aplicación asigna memoria y otra accede a esa memoria, pero ¿cómo se comunican? ¿No es inseguro hacer esto?
Respuestas:
El mecanismo de interproceso de impulso tiene tres componentes necesarios para trabajar:
archivo mapeado en memoria: es necesario crear un archivo mapeado en memoria y pasarlo a un asignador boost.interprocess. Este asignador tomará fragmentos del archivo y los usará como si fueran devueltos por un std :: allocator, con la asignación aplicada para que la memoria sea compatible con la memoria específica en proceso.
boost.interprocess container; Este tipo de contenedor utilizará la memoria devuelta por el asignador y ofrecerá una interfaz similar a std :: container (begin / end / size / push_back, etc.).
mecanismo de sincronización; Esto puede ser cualquier mutex entre procesos y debe usarse para evitar condiciones de carrera de acceso a datos.
La memoria asignada es en realidad un archivo mapeado de memoria compartida. La comunicación es indirecta, con ambas aplicaciones configurando o leyendo los datos, según lo necesiten. La seguridad proviene del uso de primitivas de sincronización entre procesos.
fuente
la memoria compartida no es la imagen completa para IPC, es un mecanismo de transmisión de datos, pero aún necesita alguna forma de informar al otro proceso que algunos datos se han actualizado y están disponibles para ser leídos. La forma de hacerlo depende de usted, por lo general usaría un objeto de evento o mutex del sistema operativo, cada proceso espera a que se establezca, la escritura de la aplicación lo establece una vez que finaliza la escritura. Luego los hilos en los otros programas se despiertan y leen.
Alternativamente, puede sondear, leer los datos regularmente para obtener un valor que cambia cuando se actualizan los datos (por ejemplo, un contador incremental).
fuente
Boost utiliza la asignación de memoria de un archivo.
Tanto Unix como Windows admiten la creación de archivos que no existen en el sistema de archivos normal solo para este propósito.
Entonces necesitará sincronizar el acceso a esa memoria como lo haría si diferentes hilos tuvieran acceso a ella. Lo que significa que las lecturas concurrentes pueden ocurrir sin sincronización, pero tan pronto como un proceso desee escribir, deberá evitar que los demás accedan a él.
Las operaciones atómicas en la memoria compartida aún son posibles si desea una sincronización sin bloqueo.
fuente
std::atomic
clase de plantilla C ++ 11 ( cplusplus.com/reference/atomic ) en cada uno de los dos programas para que puedan escribir en el espacio compartido sin sincronización forzada a través de bloqueos?La memoria compartida sigue siendo solo memoria. Puede poner un mutex, spinlock o cualquier otra primitiva de sincronización allí, y usarlos para sincronizar el acceso de sus procesos a la memoria compartida, exactamente como los hilos usan esas primitivas para sincronizar el acceso a la memoria visible para ellos.
Las únicas diferencias reales son:
los subprocesos comparten toda la memoria y el mismo espacio de direcciones, por lo que los punteros sin procesar funcionan para ellos. La memoria compartida entre procesos funciona exactamente igual, pero puede asignarse a diferentes direcciones en cada proceso, por lo que no puede simplemente pasar punteros sin procesar entre ellos
Algunas primitivas de sincronización pueden necesitar indicadores o atributos especiales para funcionar correctamente entre procesos (ver el
PTHREAD_PROCESS_SHARED
atributo para mutexes de hilos POSIX, por ejemplo). En realidad, esto no tiene que ver con la memoria y la sincronización en sí mismas, sino debido a la interacción kernel / Scheduler necesaria para despertar a los camareros dormidos.Entonces:
De la misma forma en que diferentes hilos se comunican, permitiendo las advertencias anteriores
Sí, es exactamente tan inseguro que los procesos se comuniquen a través de la memoria compartida como lo es para que los hilos se comuniquen a través de la memoria compartida, y necesitan una sincronización equivalente (o idéntica) para que sea seguro.
fuente
Tenga en cuenta que C y C ++ son lenguajes diferentes.
La memoria compartida es imposible en C11 puramente estándar , o C ++ 11 (ya que el estándar no define eso), o incluso C ++ 14 (cuyo borrador n3690 , y presumiblemente estándar oficial, no menciona la memoria compartida fuera del multihilo ) Por lo tanto, necesita bibliotecas adicionales para obtener memoria compartida. Pero algunos sistemas operativos tienen soporte para memoria compartida. Por lo tanto, existen varias bibliotecas que proporcionan memoria compartida, creadas sobre los servicios existentes del sistema operativo. Quizás podría considerar usar la biblioteca de marco POCO (que resume los detalles específicos del sistema operativo)
Para Linux (y tal vez POSIX), busque en shm_overview (7) . Tendrá que sincronizar, así que vea también sem_overview (7)
VXWorks (que no sé, pero busqué en Google) tiene VxMP
Necesita comprender cuidadosamente lo que realmente está sucediendo. Probablemente desee compartir solo datos antiguos simples
struct
(¡no clases de C ++!) Y debe tener mucho cuidado con las direcciones (cada proceso puede obtener direcciones diferentes para el segmento común de memoria compartida) y la sincronización.Alternativamente, use hilos. Observe que el estándar C ++ 11 define una biblioteca de hilos .
fuente