Memoria indestructible, procesos indestructibles.


Después de leer recientemente ( 1 , 2 , 3 ) con qué dificultad se dan los procesadores "espaciales", me pregunté involuntariamente si el "precio" para el hierro estable es tan alto, ¿tal vez valga la pena dar un paso y, por otro lado, hacer que el "software" sea resistente a factores especiales? Pero no el software de aplicación, sino su entorno de ejecución: compilador, sistema operativo. ¿Es posible hacer que la ejecución del programa en cualquier momento sea posible interrumpir, reiniciar el sistema y continuar desde el mismo lugar (o casi el mismo)? Al final, hay hibernación .

Efectos de la radiación


Casi todo lo que vuela desde el espacio es capaz de interrumpir el funcionamiento del microcircuito, es solo una cuestión de la cantidad de energía que "trajo" con él. Incluso un fotón, si tiene una longitud de onda de rayos gamma, puede superar varios centímetros de aluminio e ionizar el (los) átomo (s) o incluso causar un efecto fotoeléctrico nuclear . Un electrón no puede penetrar a través de ningún obstáculo denso, pero si se acelera con mayor fuerza, emitirá una cantidad cuántica gamma al frenar con todas las consecuencias resultantes. Dado que la vida media de un neutrón libre es de aproximadamente 10 minutos, un neutrón raro (y muy rápido) nos llega desde el Sol. Pero los núcleos de cualquier cosa pasan volando y también son capaces de hacer cosas. Los neutrinos tal vez no se vean en algo así.

¿Cómo no recordar a Piglet con él? "Es difícil ser valiente cuando solo eres un ser muy pequeño".

Las consecuencias de la radiación cósmica que ingresa a un semiconductor pueden ser diferentes. Esta es la ionización de los átomos y la violación de la red cristalina y las reacciones nucleares. Aquí es donde se describe el dopaje de silicio con neutrones térmicos en un reactor atómico, cuando Si (30) se convierte en P (31), y se logran las propiedades deseadas de los semiconductores. No vale la pena volver a contar los maravillosos artículos mencionados, solo notaremos lo siguiente:

  1. Algunos efectos tienen un efecto a corto plazo y no tienen efectos a largo plazo. Pueden conducir a errores que pueden repararse, ya sea hardware o software. En el peor de los casos, un reinicio ayuda.
  2. , . - .
  3. .

Tenga en cuenta que los efectos de los tipos 2 y 3, si se pudieron detener, conducen a una degradación gradual del microcircuito. Por ejemplo, si uno de los (incluso 4) sumadores "se quemó" en el procesador superescalar , puede (al menos no especulativamente) deshabilitar físicamente el poder de la víctima y usar los tres restantes, externamente solo se notará una caída en el rendimiento. Del mismo modo, si uno de los registros internos de la agrupación está dañado, puede estar marcado como "siempre ocupado" y no podrá participar en la planificación de las operaciones. La unidad de memoria puede no estar disponible. ... Pero si algo irreparable se ha deteriorado, tendrá que aumentar la reserva de frío. Si él es.

“Permanecer en una reserva fría, por cierto, no protege al microcircuito de la acumulación de la dosis, e incluso de la acumulación de carga en el aislante de la puerta. Además, se conocen microcircuitos en los que la degradación de la dosis sin fuente de alimentación es incluso peor que con ella. Pero todos los efectos únicos que causan fallas graves requieren la inclusión del chip. Con la alimentación apagada, puede haber efectos de sesgo, pero no son importantes para la lógica digital ". (amartología)

Por lo tanto, hay dos factores

  • en cualquier momento, puede ocurrir una falla, que se trata mediante un reinicio
  • el sistema se degradará gradualmente (secuencia de fallas), la mayor parte del trabajo ocurrirá en condiciones de degradación parcial

¿Cómo vives con todo esto? Debido a la reserva / triplicación con votación en toda la jerarquía de bloques funcionales. En sí mismo, triplicar no es una panacea, es necesario para comprender cuál de los resultados es correcto cuando falla uno de los componentes. Luego, el componente fallido puede reiniciarse y alinearse con dos trabajadores. Pero en caso de una falla, cuando el componente no puede ponerse en condiciones de funcionamiento, solo la reserva fría, si la hubiera, ayudará.

Incluso si la falla no parece crítica, puede causar serios problemas. Supongamos que tenemos tres computadoras que funcionan sincrónicamente, en una de ellas (hipotética, mencionada anteriormente) uno de los sumadores falló. Esto no es un problema desde el punto de vista de una computadora que ha permanecido operativa, pero es un problema para todo el sistema desde la computadora afectada comenzará a retrasarse sistemáticamente y se requerirán esfuerzos serios para la sincronización general.

Otro ejemplo, una falla de memoria, como resultado de la cual parte de su rango (incluso una página) se ha vuelto inutilizable, no es crítica desde el punto de vista de una sola computadora. Después del diagnóstico, el sistema operativo puede hacer frente a este problema sin utilizar este rango. Pero desde el punto de vista del sistema troyano, esto es un desastre. Ahora, si hay una falla (que se trata reiniciando), tendremos que llevar la computadora fallida a un estado idéntico a cualquiera de las restantes, pero esto es imposible porque en otras computadoras, este rango funciona y probablemente se usa. En principio, es posible prohibir este rango en las tres computadoras, sin embargo, no es obvio que sea posible hacerlo sin reiniciar todas las computadoras.

Es una situación paradójica cuando un sistema que se troya en el nivel superior es menos confiable en comparación con una sola computadora que puede adaptarse a la degradación gradual.

Vale la pena mencionar el enfoque llamado Lock-step , cuando dos núcleos realizan la misma tarea con un cambio de uno o dos ciclos de reloj, y luego se comparan los resultados. Si no son iguales, se vuelve a ejecutar algún fragmento de código. Esto no funciona si hay un error en la memoria o en la caché general, sin embargo, tiene su propia protección.

También hay un enfoque en el que el compilador repite la ejecución de parte de los comandos y compara los resultados. Una versión tan suave de Lock-step.

Ambos enfoques (graciasamartologíapor punta): un intento de detectar una falla e intentar solucionarlo con "poca sangre", sin reiniciar. Es más probable que consideremos la situación cuando ocurre una falla grave o una falla no crítica y es inevitable un reinicio. Cómo asegurarse de que el programa sin ningún esfuerzo especial por su parte pueda ser interrumpido en cualquier momento, y luego continuar sin pérdidas serias.

Cómo enseñar hardware y sistema operativo a adaptarse a la degradación gradual es un tema para otra discusión.

Y si


La idea de una memoria estable / persistente no es nueva en sí misma, por lo que el respetado Dmitry Zavalishin (dzavalishin) propuso su concepto de memoria persistente . En sus manos, esto dio lugar a un sistema operativo Phantom persistente , en realidad una máquina virtual con la sobrecarga correspondiente.

Quizás, con el tiempo, las tecnologías MRAM o FRAM madurarán ... mientras estén en bruto.

También hay una leyenda sobre la computadora a bordo del cohete R-36M (15L579?), Que pudo lanzarse a través de una nube radiactiva inmediatamente después de una explosión nuclear cercana. La memoria aplicada en los núcleos de ferrita es inmune a la radiación. El ciclo de grabación de tal memoria es del orden de unidades de microsegundos., por lo tanto, durante el tiempo que el cohete vuela unos pocos decímetros, hubo una oportunidad física para mantener el contexto del procesador: el contenido de los registros y las banderas. Al despertar en un entorno seguro, el procesador continuó funcionando.
Suena creíble

Hay algunos peros:

  1. La hibernación en su forma actual no es adecuada. Toma algo de esfuerzo y tiempo. Estamos tratando de protegernos de un fracaso repentino. No es obvio que después de esta falla, el procesador sea físicamente capaz de hacer al menos algo. Del mismo modo, en 15L579, el sistema recibe una advertencia antes de que comiencen los problemas y tiene tiempo para protegerse contra ellos.
  2. “” — , , — . , () , .
  3. , , . — -.

En general, la recuperación de fallos es esencialmente una contraparte del manejo de excepciones. En realidad, la falla en sí en la mayoría de los casos comienza como una interrupción de hardware. La diferencia es que después de la excepción, simplemente podemos continuar trabajando, y en este caso primero tenemos que restaurar el contexto de trabajo: la memoria y el estado del núcleo del sistema operativo. Pero la parte final se ve igual.

Primero, cómo debería verse desde el lado del programador de aplicaciones.

Una mirada desde fuera del núcleo del sistema operativo


Dado que recuperarse de fallas es similar a recuperarse de lanzar una excepción, trabajar con él puede ser similar. Por ejemplo, en C ++ heredamos la clase std :: tremendo_error de la excepción std ::, la capturamos en un bloque regular try / catch y organizamos el procesamiento.

Sin embargo, al autor le gusta más la semántica de setjmp / longjmp (SJLJ) porque:

  • esto es conciso, solo llame al setjmp analógico (& buf) y reanude el trabajo desde el mismo lugar
  • incluso no se requiere "& buf", solo se llama a una función del sistema que almacena el estado actual
  • Además de C ++, hay otros lenguajes geniales, no en todas partes hay manejo de excepciones, pero en todas partes hay una llamada a las funciones del sistema
  • y no hay necesidad de modificar el idioma, porque originalmente íbamos a actuar de la manera más invasiva posible

En un momento, SJLJ perdió la técnica DWARF (estrictamente hablando, el enano es solo un formato para registrar información) en el manejo de excepciones debido al peor rendimiento, el rendimiento no es tan importante aquí. En cualquier caso, mantener el estado no será barato; uno debe abordarlo de manera responsable.

Una mirada desde el interior del núcleo del sistema operativo


¿Qué necesita ser guardado, en qué consiste el contexto de la ejecución del proceso?

  1. Para cada subproceso en modo de usuario, el "jmp_buf" actual con los registros necesarios, esto significa que el sistema operativo debe detener todos los subprocesos del proceso de llamada antes de guardar los datos
  2. , — . (: ), (ex: ).
  3. . (ex: ), (ex: TCP ). .
  4. , . ,
  5. . , . , — . .. .

    , , . .
  6. , .

No se requiere información para transcodificar desde la memoria virtual a la física y viceversa; al reiniciar, esta información se volverá a crear por sí misma, posiblemente de una manera diferente.

En cuanto a trabajar con el sistema de archivos. Entre los sistemas de archivos, hay los transaccionales. Si la aplicación requiere un comportamiento transaccional preciso, la preservación del contexto del proceso debe sincronizarse con la confirmación de la transacción del sistema de archivos. Por otro lado, por ejemplo, para grabar registros de texto, es lógico usar un sistema de archivos normal, la transaccionalidad aquí sería extraña.

De todo lo anterior, las preguntas más importantes son causadas por la preservación de los contenidos de la memoria; el volumen de todo lo demás es insignificante en comparación con esto.
Por ejemplo, tiempo de ejecuciónla biblioteca almacena las asignaciones de memoria, las solicita del sistema en fragmentos relativamente grandes y se distribuye. Por lo tanto, crear / eliminar segmentos es relativamente poco.

Pero los programas funcionan continuamente con la memoria, en esencia es el subsistema de memoria el que generalmente es el cuello de botella en los cálculos. Y todo lo que puede simplificar nuestras vidas es el soporte de hardware para banderas de páginas modificadas. Se espera que entre los estados guardados, no aparezcan demasiadas páginas modificadas.

En base a esto, en el futuro trataremos los contenidos de la memoria.

Guardar el contenido de la memoria


El comportamiento deseado está cerca de las bases de datos: el DBMS puede "caer" en cualquier momento, pero el trabajo realizado continuará hasta la última confirmación. Esto se logra manteniendo un registro de transacciones, ingresando en qué registros de confirmación legalizará todos los cambios realizados en la transacción.

Pero, dado que el término " memoria transaccional " está ocupado, presentaremos otro: "memoria indestructible".

De antemano puede ver dos métodos por los cuales se puede implementar esta memoria indestructible.

Opción uno , llamémoslo "sin pretensiones".
La idea principal es que todos los datos modificados en una transacción deben colocarse en la RAM. Aquellos. durante la operación, el mecanismo de intercambio no guarda nada en el disco, pero durante la confirmación, todas las páginas cambiadas se guardan en el archivo de intercambio.

La información sobre los segmentos seleccionados y su conexión con el lugar en el archivo de intercambio se escribe en el registro. Durante la operación, esta información se acumula y se registra durante la confirmación. Al reiniciar, el sistema tiene la capacidad de crear segmentos de nuevo. El mecanismo de intercambio podrá extraerlos y el programa interrumpido recibirá mágicamente sus datos.

Sin embargo, en este modo es imposible, por ejemplo, asignar una matriz de callocth más grande que la memoria disponible (por cierto , la malloctth es posible). Sin embargo, esto en cualquier caso no sería una muy buena idea.

Incluso si dicho régimen se aplica solo a procesos que se han declarado "indestructibles", la cantidad de memoria ocupada por las transacciones actuales de todos esos procesos no puede exceder la disponibilidad física. El mecanismo de intercambio en realidad detiene el intercambio y se convierte en un mecanismo para almacenar transacciones recientes.

Todo esto impone una cierta disciplina a los desarrolladores de aplicaciones, puede conducir a una carga desigual en el disco, en general, esto no es exactamente lo que queríamos, pero puede funcionar en sistemas integrados.

Un inconveniente importante de esta opción es que un error fatal durante la confirmación, cuando solo se escribió una parte de las páginas, lleva el proceso correspondiente a un estado inestable, después del cual deberá detenerse.
Resulta algún tipo de inviolabilidad del 50%.

Opción dos , "Sombra"
Para actuar como administrador de transacciones, debe ser un administrador de transacciones.

Definamos entidades:

  1. El archivo de página contiene páginas de datos, por lo que el tamaño es un múltiplo del tamaño de la página. Decimos el archivo, nos referimos a la sección más bien, porque Un tamaño fijo mejora la estabilidad del sistema.
  2. Asignador de página de archivo de paginación . Es necesario seleccionar una página no solo para los datos del usuario, sino también, por ejemplo, para registrar el estado del asignador. Además de todo lo mencionado anteriormente.
  3. . , . , ,
    (= , ).
  4. . —
    • ID
    • ( )
    • ID .

    - TLB, .. .

    ( ) . . , ex: (Buddy Allocator) .

    , . .
  5. . COW (copy on write) . , . COW, - , . .

    — - , “dirty”. .
  6. (). .

    : , .

    . , . . , , . . , ? , .

    , .

    (= , , , ).


    (=, ). .

    . , . , , , .

    , . , . .

    — . , , , , .
    , , .

    .
  7. . , , — . , ?

    — . , . , . , .. .

    — , SSD ! , SSD ( “” ) .

    , .

    — . , . , . ( ).

    , , , . , , . , , , . , — . .
  8. Checkpoint.

    , , , , . — . , . checkpoint. .

    . . - checkpoint- . .

    , . - .

    checkpoint-. , / .

    -, - /, . , ( ...). .

    . . . , . — , checkpoint.


Es una pena que no haya dispositivos de almacenamiento que sean completamente resistentes al funcionamiento a largo plazo en condiciones espaciales. Los núcleos de ferrita eran resistentes a la radiación, pero tenían sus propios problemas específicos debido a la gran cantidad de uniones soldadas. Además de baja capacidad, baja velocidad y alta complejidad de fabricación.

Sin embargo, debe poder escribir y leer de manera confiable estos datos.

Un candidato obvio es la memoria flash. Inicialmente, Flash no era altamente confiable debido al bajo número de ciclos de escritura válidos, por lo que se desarrollaron métodos especiales para trabajar con él .

Anteriormente se mencionó que el triplicado se usa para trabajar con elementos poco confiables, RAID1 es suficiente aquíporque Si la grabación falla debido a los valores de control, se sabe cuál de las dos páginas se escribió incorrectamente y debe sobrescribirse.

Total


Bueno, ahora tenemos en nuestras manos las cuatro letras de la palabra ACID .

A - atomicidad, logrado
C - consistencia,
I - aislamiento es evidente , se logra de forma natural. Si no considera el caso de la memoria compartida. Y por el momento no lo estamos considerando.

D - persistencia, la única vez que intentamos hacer trampa cuando lanzamos el proceso después de una confirmación sin esperar la grabación física de todos los datos en su memoria en el disco. En el peor de los casos, esto conducirá a una reversión a la transacción anterior. No está claro cuán crítico es esto tanto para el rendimiento como para la durabilidad.

PD. Solo una nota rapida. No tenemos un mecanismo para las transacciones de reversión, la reversión solo puede ser un error fatal. Técnicamente (parece) es fácil implementar un programa de reversión de transacciones como un análogo de longjmp. Pero esta es una versión mucho más avanzada de longjmp ya que restaura completamente el estado interno del proceso en el momento de "setjmp", evitando pérdidas de memoria, permite la transición no solo de abajo hacia arriba de la pila ...

PPS . Quizás, el servidor OpenLink Virtouso DBMS , disponible también como software libre , pueda considerarse el prototipo del administrador de transacciones .

PPA . Gracias a Valery Shunkov (amartología) y Anton Bondarev (abondarev) para una discusión significativa y muy útil.

PPPPS . Ilustración de Anna Rusakova .

All Articles