Se puede forzar un accidente si se produce una escritura en una posición de memoria dada con granularidad más fina que la página?

StackOverflow https://stackoverflow.com/questions/2484959

Pregunta

Estoy escribiendo un programa que por razones de rendimiento utiliza la memoria compartida (enchufes y tuberías que se han evaluado las alternativas, y no son lo suficientemente rápido para mi tarea, en términos generales cualquier método IPC que implica copias es demasiado lento). En la región de memoria compartida que estoy escribiendo muchas estructuras de un tamaño fijo. Hay un programa responsable de escribir las estructuras en la memoria compartida, y muchos clientes que decían de él. Sin embargo, no es un miembro de cada estructura que los clientes necesitan para escribir (un contador de referencia, que se actualizará de forma atómica). Todos los demás miembros deben leerse sólo para los clientes.

Dado que los clientes necesitan cambiar que un miembro, no pueden mapear la región de memoria compartida como de sólo lectura. Pero no deben ser jugando con los otros miembros, ya sea, y puesto que estos programas están escritos en C ++, corrupción de memoria es posible. Idealmente, debería ser tan difícil como sea posible para un cliente se bloquee otra. Sólo estoy preocupado por los clientes con errores, no los 'malos', por lo que se permite soluciones imperfectas.

Puedo tratar de dejar de clientes sobrescriban declarando los miembros de la cabecera se utilizan como const, pero eso no evitará daños en la memoria (desbordamientos de buffer, malos moldes, etc.) de sobreescritura. Puedo insertar canarios , pero luego tengo que pagar constantemente el costo de la verificación.

En lugar de almacenar el elemento de cómputo de referencia directa, que podía almacenar un puntero a los datos reales en una escritura separada asignada única página, manteniendo las estructuras en las páginas asignadas solamente leer. Esto funciona, el sistema operativo forzará mi aplicación se bloquee si trato de escribir en la punta de los datos, pero el almacenamiento indirecta puede ser indeseable cuando se trata de escribir bloqueo algoritmos libres , porque necesitan seguir a otro nivel de indirección pueden cambiar si algo se puede hacer de forma atómica.

¿Hay alguna manera de marcar las áreas más pequeñas de la memoria de tal manera que escribirlos hará que su aplicación para saltar? Algunas plataformas de hardware tienen puntos de observación, y tal vez podría activar uno de los que tienen ensamblado en línea, pero estaría limitado a solamente 4 a la vez en x86 de 32 bits y cada uno de ellos sólo podrían cubrir parte de la estructura porque están limitados a 4 bytes. También haría que mi programa de depuración doloroso;)

Edit: He encontrado esto en lugar de ojos apareciendo papel , pero por desgracia, requiere el uso de memoria ECC y un núcleo de Linux modificado.

¿Fue útil?

Solución

No creo que su posible hacer unos pocos bits de sólo lectura como que en el nivel de sistema operativo.

Una cosa que me ocurrió hace un momento es que se puede poner la cuenta de referencia en una página diferente, como usted sugiere. Si las estructuras son de un tamaño común, y todos están en posiciones de memoria secuenciales podría utilizar la aritmética de punteros para localizar un contador de referencia del puntero de estructuras, en lugar de tener un puntero dentro de la estructura. Esto podría ser mejor que tener un puntero para su caso de uso.

long *refCountersBase;//The start address of the ref counters page
MyStruct *structsBase;//The start address of your structures page

//get address to reference counter
long *getRefCounter(MyStruct *myStruct )
{
    size_t n = myStruct - structsBase;
    long *ref = refCountersBase + n;
    return ref;
}

Otros consejos

Usted tendría que agregar un controlador de señal para SIGSEGV la que se recupera de la excepción, pero sólo para ciertas direcciones. Un punto de partida podría ser http://www.opengroup.org/onlinepubs /009695399/basedefs/signal.h.html y la documentación correspondiente para su sistema operativo.

Editar Creo que lo que quiere es llevar a cabo la grabación y regresar si la dirección de escritura es en realidad estaba bien, y la cola-llamar al manejador de excepciones anterior (el puntero se obtiene cuando se instale su excepción manejador) si desea propagar la excepción. No tengo experiencia en estas cosas sin embargo.

Nunca he oído hablar de la aplicación de sólo lectura en menos de una granularidad página, por lo que podría estar fuera de suerte en ese sentido a menos que pueda poner cada estructura en dos páginas. Si se lo puede permitir dos páginas por estructura se puede poner el recuento ref en una de las páginas y hacer que el otro sólo lectura.

Se puede escribir una API en lugar de utilizar los encabezados. Obligar a los clientes a utilizar la API eliminaría la mayoría de los problemas de corrupción.

Mantener los datos con el contador de referencia en lugar de en una página diferente ayudará con la localidad de los datos y así mejorar el rendimiento de la caché.

Es necesario tener en cuenta que un lector puede tener un problema y no actualizar adecuadamente su recuento ref. También que el escritor puede fallar para completar una actualización. El hacer frente a estas cosas requiere comprobaciones adicionales. Se pueden combinar estos controles con la API. Puede valer la pena experimentar para medir las consecuencias en el rendimiento de algún tipo de comprobación de integridad. Puede ser lo suficientemente rápido como para mantener una suma de comprobación, algo tan simple como Adler32.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top