2010-07-07 11 views
12

Estaba trabajando en una cola segura para subprocesos respaldada por archivos mapeados en memoria que utilizaban el interproceso de refuerzo bastante. Lo presenté para la revisión del código y un desarrollador con más años de experiencia de lo que tengo en este planeta dijo que no creía que boost :: interprocess estaba "listo para el horario de máxima audiencia" y que debería usar pthreads directamente.¿Boost :: interprocess está listo para el horario de máxima audiencia?

Creo que es principalmente FUD. Personalmente creo que es ridículo volver a implementar cosas como upgradable_named_mutex o boost :: interprocess :: deque, pero tengo curiosidad por saber qué piensan los demás. No pude encontrar ningún dato para respaldar su reclamo, pero tal vez solo estoy desinformado o soy ingenuo. ¡Stackoverflow me ilumina!

Respuesta

19

Intenté usar boost :: interprocess para un proyecto y salí con sentimientos encontrados. Mi principal preocupación es el diseño de boost :: offset_ptr y cómo maneja los valores NULL; en resumen, boost :: interprocess puede hacer que el diagnóstico de los errores de los punteros NULL sea realmente doloroso. El problema es que un segmento de memoria compartida se asigna en algún lugar en el medio del espacio de direcciones de su proceso, lo que significa que "NULL" offset_ptr, cuando se desreferencia, apuntará a una ubicación de memoria válida, por lo que su aplicación no va a segfault . Esto significa que cuando la aplicación finalmente se cuelga puede tardar mucho tiempo después de que se cometió el error, lo que dificulta la depuración.

Pero empeora. Los mutexes y las condiciones que aumentan ::: los usos interproceso se almacenan internamente al comienzo del segmento. Por lo tanto, si accidentalmente escribe en some_null_offset_ptr-> some_member, comenzará a sobrescribir la maquinaria interna del segmento boost :: interprocess y obtendrá un comportamiento totalmente extraño y difícil de entender. Escribir un código que coordine múltiples procesos y lidiar con las posibles condiciones de carrera puede ser difícil por sí solo, por lo que fue doblemente exasperante. Terminé escribiendo mi propia biblioteca de memoria compartida mínima y utilizando la llamada al sistema POSIX mprotect para hacer que la primera página de mis segmentos de memoria compartida no se pudiera leer y escribir, lo que hizo que aparecieran errores NULOS inmediatamente (desperdicia una página de memoria pero un pequeño sacrificio vale la pena a menos que estés en un sistema integrado). Podría intentar usar boost :: interprocess pero todavía llamar manualmente a mprotect, pero eso no funcionará porque boost esperará que pueda escribir en esa información interna que almacena al comienzo del segmento.

Finalmente, offset_ptr asume que está almacenando punteros dentro de un segmento de memoria compartida a otros puntos en el mismo segmento de memoria compartida. Si sabe que va a tener múltiples segmentos de memoria compartida (sabía que este sería el caso porque para mí porque tenía un segmento de escritura y uno de solo lectura) que almacenaría los punteros uno dentro del otro, offset_ptr se interpondría en su camino y tienes que hacer un montón de conversiones manuales. En mi biblioteca de memoria compartida hice una clase de plantilla SegmentPtr<i> donde SegmentPtr<0> serían punteros en un segmento, SegmentPtr<1> serían punteros en otro segmento, etc. para que no se puedan mezclar (solo puede hacer esto si conoce el número de segmentos en tiempo de compilación).

Debe sopesar el costo de implementar todo usted mismo en comparación con el tiempo de depuración adicional que va a gastar rastrear errores NULL y potencialmente mezclar punteros a diferentes segmentos (este último no es necesariamente un problema para usted). Para mí, valió la pena implementarlo yo mismo, pero no estaba haciendo un uso intensivo de las estructuras de datos boost :: interprocess, por lo que valió la pena. Si la biblioteca puede ser de código abierto en el futuro (no depende de mí) lo actualizaré con un enlace, pero por ahora no contengo la respiración; p

En lo que respecta a su compañero de trabajo: no lo hice Experimenta cualquier inestabilidad o error en boost :: interprocess. Simplemente creo que su diseño hace que sea más difícil encontrar errores en tu propio código.

5

Hemos estado utilizando la memoria compartida boost :: interprocess y interprocess.synchronization_mechanisms.message_queue durante aproximadamente 6 meses y encontramos que el código es confiable, estable y bastante fácil de usar.

Mantenemos nuestros datos en estructuras de tamaño fijo bastante simples (aunque 12 regiones con un total de 2 + gb de tamaño) y usamos el código de ejemplo boost :: interprocess tal cual y casi no tuvimos problemas.

Encontramos dos elementos a tener en cuenta cuando usamos boost :: interprocess con windows.

  1. Revisión Boost Shared Memory & Windows. Si usa los objetos predeterminados #include <boost/interprocess/shared_memory_object.hpp>, entonces solo puede aumentar el tamaño de la región mapeada en memoria reiniciando Windows primero. Esto se debe a la forma en que boost utiliza una tienda de respaldo de archivos.
  2. La clase message_queue usa el valor predeterminado shared_memory_object. Entonces, si es necesario aumentar el tamaño del mensaje, reinicie Windows nuevamente.

No estoy tratando de decir que la publicación de Joseph Garvin sobre sus problemas con boost :: interprocess no era válida. Creo que las diferencias en nuestras experiencias están relacionadas con el uso de diferentes aspectos de la biblioteca. Estoy de acuerdo con él en que no parece haber problemas de estabilidad en boost :: interprocess.

+4

En lugar de reiniciar Windows, ¿quiso decir que reiniciaba la aplicación? No veo nada acerca de reiniciar Windows en su enlace, o entiendo cómo usar un archivo como almacén de respaldo podría hacer que sea necesario O_o –

Cuestiones relacionadas