lunes, 6 de mayo de 2013

Kernel Linux y Peticiones de Interrupción (S.O.S, se me ha quedado frito el pingüino)

Usando un sistema GNU/Linux rara vez habremos sufrido un cuelgue. Lo más “normal” es sufrir un parón del sistema gráfico (el sistema de ventanas X, comúnmente gestionado por el servidor X.org), y pongo normal entre comillas porque como ya digo, sufrir algún cuelgue que evite por completo la interacción con el ordenador es extremadamente raro, aunque sea en la capa de ejecución de espacio de usuario.
Como información adicional al tema principal de este post, diré que en caso de que lo que se haya quedado congelado sea el entorno gráfico, se puede reiniciar dicho sistema con un CTRL + ALT + BACKSPACE (backspace = tecla de borrado hacia atrás, no tecla SUPRIMIR) o bien se puede abrir una TTY (terminal en modo texto, como curiosidad, TTY viene de TeleTYpewriter) con CTRL + ALT +F(1-12) (teclas de F1 a F12) y realizar un /etc/init.d/nombre_del_script_ejecutable_de_tu_gestor_de_sesiones restart (nombre_del_ejecutable blah blah sería por ejemplo GDM para GNOME y KDM para KDE por citar los más comunes, si en sistema coexisten los dos, tendrás activo uno de los dos, el que hayas escogido al instalar el segundo entorno de escritorio).


En la última versión del servidor X el CTRL+ALT+BACKSPACE ha quedado deshabilitado. Si se quiere mantener activo, hay que añadir al archivo /etc/X11/xorg.conf las siguientes líneas:

Section "ServerFlags"

    Option "DontZap" "false"

EndSection


En fin, retomando el hilo principal del artículo de hoy. Del kernel linux y la posibilidad de realizar peticiones de interrupción software manualmente con nuestro teclado. En el caso de que el sistema aparentemente haya quedado completamente frito, aún nos queda una última posibilidad para realizar un apagado del sistema completamente seguro sin correr el riesgo de perder datos, etc. Esta posibilidad consiste en hacer saltar las correspondientes IRQs de tal forma que sean atendidas por las partes que aún quedan funcionales en el sistema (un cuelgue fatal pero no total significaría un Kernel Oops, y un cuelgue completo un Kernel Panic -el equivalente a un BSOD en Windows-, sucesos que de momento sólo he experimentado realizando overclocking, es decir, situaciones en las que el hardware puede ser bastante inestable). Para ello, haremos uso de la tabla de peticiones que podemos encontrar, dentro de las fuentes del kernel, en el archivo drivers/char/sysrq.c.

static struct sysrq_key_op *sysrq_key_table[36] = {
 &sysrq_loglevel_op,  /* 0 */
 &sysrq_loglevel_op,  /* 1 */
 &sysrq_loglevel_op,  /* 2 */
 &sysrq_loglevel_op,  /* 3 */
 &sysrq_loglevel_op,  /* 4 */
 &sysrq_loglevel_op,  /* 5 */
 &sysrq_loglevel_op,  /* 6 */
 &sysrq_loglevel_op,  /* 7 */
 &sysrq_loglevel_op,  /* 8 */
 &sysrq_loglevel_op,  /* 9 */

 /*
  * a: Don't use for system provided sysrqs, it is handled specially on
  * sparc and will never arrive.
  */
 NULL,    /* a */
 &sysrq_reboot_op,  /* b */
 &sysrq_crashdump_op,  /* c & ibm_emac driver debug */
 &sysrq_showlocks_op,  /* d */
 &sysrq_term_op,   /* e */
 &sysrq_moom_op,   /* f */
 /* g: May be registered by ppc for kgdb */
 NULL,    /* g */
 NULL,    /* h */
 &sysrq_kill_op,   /* i */
 NULL,    /* j */
 &sysrq_SAK_op,   /* k */
#ifdef CONFIG_SMP
 &sysrq_showallcpus_op,  /* l */
#else
 NULL,    /* l */
#endif
 &sysrq_showmem_op,  /* m */
 &sysrq_unrt_op,   /* n */
 /* o: This will often be registered as 'Off' at init time */
 NULL,    /* o */
 &sysrq_showregs_op,  /* p */
 &sysrq_show_timers_op,  /* q */
 &sysrq_unraw_op,  /* r */
 &sysrq_sync_op,   /* s */
 &sysrq_showstate_op,  /* t */
 &sysrq_mountro_op,  /* u */
 /* v: May be registered at init time by SMP VOYAGER */
 NULL,    /* v */
 &sysrq_showstate_blocked_op, /* w */
 /* x: May be registered on ppc/powerpc for xmon */
 NULL,    /* x */
 /* y: May be registered on sparc64 for global register dump */
 NULL,    /* y */
 NULL    /* z */
};
 
Como se puede ver, es un vector de punteros a las diferentes structs que especifican la función que manejará la activación de la operación correspondiente a nivel de interrupción software. Un ejemplo:


static void sysrq_handle_reboot(int key, struct tty_struct *tty)
{
 lockdep_off();
 local_irq_enable();
 emergency_restart();
}
static struct sysrq_key_op sysrq_reboot_op = {
 .handler = sysrq_handle_reboot,
 .help_msg = "reBoot",
 .action_msg = "Resetting",
 .enable_mask = SYSRQ_ENABLE_BOOT,
};
 
Se puede ver en la struct sysrq_reboot_op que la función (handler) a manejar la petición de reset es sysrq_handle_reboot, que se puede ver justo encima. Todas estas llamadas son tratadas por las funciones __handle_syrq y handle_sysrq que a su vez son llamadas por el propio kernel en cuanto recibe la señal correspondiente. Bien, si se quiere saber más sobre el funcionamiento interno, es leerse el archivo sysrq.c junto con todos los headers que utiliza y ver lo que hace.
Así pues, una vez sabemos las peticiones disponibles y las teclas correspondientes para activarlas (Linux Magic System Request Key), sólo queda saber como aplicarlas. Es muy fácil: ALT + PetSis/Interrupt/Pausa + Magic_Key. Entre cada pulsación de Magic Key es conveniente esperar unos segundos (cinco o más, por decir algo) a que el kernel realice las operaciones correspondientes.


En caso de fritura del kernel, nos interesaría realizar la siguiente secuencia:
  1. ALT+PetSis+R
  2. ALT+PetSis+E
  3. ALT+PetSis+I
  4. ALT+PetSis+S
  5. ALT+PetSis+U
  6. ALT+PetSis+B
Es decir, REISUB. Como podéis ver, lo que vamos haciendo a cada paso es lo siguiente:

  1. Devolvemos el teclado al estado K_XLATE. Al menos con un kernel Linux, el teclado puede funcionar en tres modos: K_RAW, K_MEDIUMRAW y “cooked”, el cual puede ser K_XLATE o K_UNICODE. En el modo K_RAW, el scancode de la tecla pulsada es enviada directamente a la TTY. En K_MEDIUMRAW los scancodes enviados por el teclado son traducidos a los keycodes correspondientes. Con K_XLATE y K_UNICODE (modo “cooked”), los scancodes envíados por el teclado son traducidos a keycodes y éstos luego son traducidos al keysym correspondiente según la localización de teclado del usuario y el mapeado a usar según las teclas de control que estén presionadas (shift, shift lock, num. lock, etc.).
  2. Envía el signal SIGTERM a todos los procesos de tal forma que puedan terminar ordenadamente, guardando sus datos, etc.
  3. Envía el signal SIGKILL a todos los procesos restantes, de tal forma que son terminados de forma brusca y sin rechistar, asegurándonos que no quede ya ningún proceso activo. Nótese que tanto con ésta orden como la anterior, el proceso Init seguirá en pie. Si quisieramos acabar con Init habría que usar la tecla K, haciendo el equivalente a un SAK.
  4. Realiza un SYNC de emergencia. Toda la buffer caché es enviada a disco de inmediato, evitando por tanto perder cualquier tipo de dato. Hoy día quizá no sea tampoco muy crucial debido a los sistemas de archivos transaccionales que se usan, pero nunca está de más ya que siempre puede quedar algo en el aire que de otro modo con un hard reset perderíamos.
  5. Desmonta el sistema de archivos y lo vuelve a montar en sólo lectura.
  6. Reinicia el sistema.

Y con esta secuencia realizamos un reinicio del sistema limpio. Más de una vez en el caso de Windows vendría bien algo semejante, a pesar de que con las funciones de guardado automático de las suites ofimáticas más comunes el impacto de una congelación repentina haya sido mitigado, si la pérdida de tiempo puede ser reducida a 0, mejor que mejor, ¿no?. A niveles más serios, la utilidad de las “Magic Keys” creo que es bastante evidente, por muchos sistemas de backup, configuración del sistema al milímetro, etc. que se tenga, en caso de obtener un parón en el sistema las consecuencias pueden ser desde que Fulanito de Tal ha perdido las direcciones de correo que acababa de escribir de N contactos importantes, hasta cosas como que en la central nuclear de Nisupu a caído el sistema de tal forma que se han perdido varios datos de control cruciales tomados hace nada, pasando por un render 3D que puede haber quedado corrupto teniendo que hacer uso del backup del día anterior.
Por último, añadir que si se quiere saber si nuestro núcleo de sistema tiene activada esta opción, tan sólo tenemos que hacer un cat de /proc/sys/kernel/sysrq. Si devuelve un 1, está activado, en caso contrario, las peticiones a sistema están desactivadas, con un echo 1 > /proc/sys/kernel/sysrq quedaría activo (también se podría recompilar el kernel con la opción de las Magic Keys activadas de forma permanente). Además, si se quieren realizar estas interrupciones de manera remota, podemos hacer un echo X > /proc/sysrq-trigger donde X es la letra correspondiente a la interrupción que queremos realizar. Evidentemente, todo esto tiene que ser con permisos de superusuario.

Enlaces de interés:

No hay comentarios:

Publicar un comentario en la entrada