2009-05-19 7 views
11

Me gustaría emular el apagado violento del sistema, es decir, acercarme lo más posible al corte de energía en un nivel de aplicación. Estamos hablando de la aplicación c/C++ en Linux. Necesito que la aplicación se resuelva solo.¿Cuál es la forma más violenta en que una aplicación puede darse por terminada? (Linux)

Actualmente Veo varias opciones:

  1. llamada exit()
  2. llamada _exit()
  3. llamada abort()
  4. hacer la división por cero o NULL eliminar la referencia.
  5. otras opciones?

¿Cuál es la mejor opción?

Parcialmente duplicado de this question

+20

Comience a ejecutar su programa, luego acceda a su computadora y, mientras el programa se está ejecutando, desenchufe el cable de alimentación. –

+0

Disculpa, solución inaceptable. – Drakosha

+0

Entonces, en un momento, la aplicación se está ejecutando; al siguiente, estás mirando un símbolo del sistema. En los días de DOS, llamé a esto "tono de marcado". – gbarry

Respuesta

14

En el nivel de aplicación, el más violento que puede obtener es _exit(). La división por cero, segfaults, etc. son todas las señales, que pueden quedar atrapadas; si no están atrapadas, son básicamente las mismas que _exit(), pero pueden dejar un núcleo en función de la señal.

Si realmente quieres un apagado completo, la mejor opción es reducir la potencia de la manera más violenta posible. Invocar/sbin/poweroff -fn es lo más cercano que puede obtener, aunque puede hacer una limpieza en el nivel de hardware en el camino de salida.

Si realmente quiere enfatizar las cosas, su mejor opción es realmente cortar la energía de verdad, instalar algún tipo de relé controlado por software en el cable de alimentación y hacer que el software corte eso. La pérdida incontrolada de poder presentará todo tipo de cosas extrañas. Por ejemplo, los datos en el disco pueden estar dañados debido a RAM losing power before the DMA controller or hard disk. Esto no es algo que pueda probar con otra cosa que no sea cortar la potencia, en la configuración de hardware de producción, en varias pruebas.

+0

Ser asesinado por un proceso externo es más abrupto y no determinista que _exit() que realiza bastante [limpieza] (http://linux.die.net/man/2/_exit), y ocurre exactamente donde el programador elige llamarlo. – Clifford

+0

En Linux, '_exit()' realiza exactamente la misma limpieza que otro proceso: la memoria asignada no se asigna (y se libera), los manejadores de archivos abiertos se cierran, los bloqueos de archivos se liberan y los silenciosos robustos se establecen en un bloqueo estado. Los procesos secundarios se vuelven a generar para init, y se notifica al padre del proceso. No se puede evitar esto, salvo estrellar el núcleo. – bdonlan

+0

@dbonlan: Leí que SIGKILL permite que el * proceso * no realice ninguna limpieza. Supongo que es posible que el sistema operativo lo haga, pero eso depende del sistema operativo. Aun así, el proceso que se abandona de manera determinista es muy diferente de ser terminado externa e imprevisiblemente. Por lo tanto, incluso si se realiza una limpieza, _exit() no presenta la condición de terminación más severa. – Clifford

7

Por qué no hacer un alto? ¿O llamas al pánico?

+0

Sea más específico, ¿qué código necesito desde dentro de la aplicación? – Drakosha

+2

sistema ("/ sbin/halt"); Call void panic (char *); http://lxr.linux.no/linux+v2.6.29/kernel/panic.c#L56 –

+0

¿Debo llamar 'detener -fn'? ¿Puedo llamar 'pánico' como una aplicación normal, es decir, no un módulo kernel? ¿En qué encabezado está? – Drakosha

11
kill -9 

Mata un proceso y no permite el funcionamiento de controladores de señal.

+0

He actualizado la pregunta un poco, por favor, eche un vistazo. – Drakosha

+0

1 ya que esto es probablemente lo más cerca que se puede llegar sin tratar de meterse con memoria asignada dentro de la aplicación – Wayne

+12

Para simular realmente un corte de corriente, vas a tener que hacerlo mejor que kill -9 ya que mata el proceso de solicitud está muerto y muerto, pero no impedirá que el sistema operativo lave los búferes de escritura sucios en el disco. En un corte de energía real, la aplicación podría haber completado algunas escrituras que el sistema operativo todavía está esperando escribir en el disco. El poder se apaga y las escrituras pendientes desaparecen. –

26

En mi humilde opinión, lo más cercano a una indignación de poder es ejecutar la aplicación en una máquina virtual y a la potencia de la máquina virtual sin apagar. En todos los demás casos en los que el sistema operativo todavía se está ejecutando cuando la aplicación finaliza, el sistema operativo hará una cierta limpieza de que no ocurriría en un corte de energía real.

+3

Bastante buena idea, básicamente se parece a la del primer comentario, pero sin arriesgar la pérdida de datos en la máquina principal real. – none

+1

Siempre que la aplicación VM no intente guardar el estado. Creo que VMWare hace eso. – ChristianLinnell

+4

No si mata -9 a la máquina virtual, el sistema operativo matará inmediatamente la máquina virtual sin preguntas – Miquel

7

Trate

raise(SIGKILL) 

en el proceso, o desde la línea de comandos:

kill -9 pid 

donde PID es el PID de su proceso (estos dos métodos son equivalentes y no deben realizar la limpieza)

+1

O bien: kill (getpid(), SIGKILL); El uso de 'raise()' fue una invención del comité de estándares de C porque el estándar C no reconoce las ID de proceso como un concepto válido. –

5

No está claro cuáles son sus requisitos. Si está haciendo pruebas de cómo se recuperará de un corte de energía, realmente debe causar un corte de energía. Incluso hacer cosas como un kernel panic permitirá que los búferes de escritura en los discos duros se vayan al ras, ya que son independientes de la CPU.

Una toma de corriente remota podría ser una solución si realmente necesita probar la falla completa.

1

He tenido pruebas de regresión que solíamos realizar cuando pulsábamos el interruptor de encendido en OFF. Mientras se hace el disco IO.

La falla en la recuperación posterior fue, bueno: una falla.

Puede comprar una fiabilidad como esa: generalmente necesitará un "certificado de usuario final".

Puede acceder al software hablando (sucio) a su UPS. UPS de APC definitivamente se apagarán con el control de software.

¿Quién dice que los sistemas no pueden encenderse por sí mismos?

+0

Déjame adivinar: ¿la aplicación era militar? – Demi

+0

Sí, el antiguo M101 CROWS –

+0

Eso explica el certificado de usuario final – Demi

2

Puede probar con una máquina virtual. Congelarlo, atornillarlo con fuerza y ​​ver qué pasa.

De lo contrario kill -9 sería la mejor solución.

2

Si necesita la aplicación termine en sí, la siguiente parece apropiada:

kill(getpid(), SIGKILL); // same as kill -9 

Si eso no es lo suficientemente violenta (y puede que no sea), entonces me gusta la idea de poner fin a una máquina virtual dentro de la cual su aplicación se está ejecutando. Debería poder instalar algo donde la aplicación pueda enviar un comando al equipo host (a través de ssh o algo similar) para terminar su propia máquina virtual.

1

recursividad infinita, debe quedarse sin espacio de pila (si no, el asesino OOM terminará el trabajo):

void a() { a(); } 

Tenedor bomba (si la aplicación no tiene ningún límite de horquilla y luego el asesino OOM debe matar a la aplicación en algún momento):

while(1) 
    fork(); 

quedado sin memoria:

while(1) 
    malloc(1); 
1

Dentro de una sola corriendo g proceso kill (getpid(), SIGKILL) es el más extremo, ya que no es posible la limpieza.

De lo contrario, pruebe una VM, o coloque una máquina de prueba en una regleta de enchufes y apáguela, si está realizando pruebas automáticas.

+0

Usar una VM y matar el proceso de VM es una gran idea ya que simulará fallas de toda la máquina sin matar al host, y ni la aplicación ni el SO tienen la oportunidad de limpiar -arriba. Sin embargo, si esto daña el sistema operativo de la máquina virtual más que la aplicación, en realidad no prueba la capacidad de recuperación de la aplicación, que me imagino que es el objetivo. – Clifford

0

Como se señaló, tratar de consumir tantos recursos como sea posible hasta que el kernel que mata:

while(1) 
    { 
    malloc(1); 
    fork(); 
    } 

Otra manera está tratando de escribir en una única página leída, sólo seguir escribiendo de memoria hasta que llegue un autobús error.

Si puede acceder al kernel, una excelente forma de eliminarlo es simplemente escribir sobre una estructura de datos que utiliza el kernel, puntos de bonificación si encuentra que una página es solo legible y marcada como escribible y luego sobrescribirla. Por cierto, la mayoría de los kernels de Linux permiten escribir en syscall_table o en la tabla de interrupciones, si escribe allí, su sistema se bloqueará con seguridad.

1

Cualquier solución en la que el proceso se resuelva programáticamente no emula una terminación asincrónica de ninguna manera. Es completamente determinista en el sentido de que terminará en el mismo punto en el código cada vez.

de sus sugerencias

  • exit() se define a "terminar normalmente, realizar la limpieza periódica de los procesos de terminación." - casi no violenta !

  • _exit() realiza un subconjunto de las operaciones de exit(), pero sigue siendo "agradable" para la aplicación, el sistema operativo y sus recursos.

  • abort() crea un SIGABRT y el sistema operativo puede optar por realizar la limpieza de algunos recursos.

  • /0 probablemente tiene un comportamiento similar a abortar()

Probablemente es mejor no tener la aplicación termina en sí, pero tienen algún proceso externo acabar con él de forma asíncrona por lo que la terminación se puede producir en cualquier punto de la ejecución. Use kill desde otro proceso o secuencia de comandos en un temporizador aleatorio, para enviar la señal SIGKILL que no puede ser capturada y no realiza ninguna limpieza. Si debe hacer que el proceso se termine, hágalo a partir de un subproceso asíncrono que se despierte después de un tiempo no determinista, y mate el proceso, pero incluso así sabrá qué subproceso se estaba ejecutando cuando termino. Incluso utilizando estos métodos, no hay forma de que un proceso se pueda finalizar mid-cpu-cycle como un verdadero poder de apagado, y cualquier salida almacenada en memoria caché o almacenada aún puede aparecer o escribirse después de la finalización del proceso.

0

En un sistema reciente, un proceso con privilegios de superusuario podría tomar la CPU en tiempo real/prioridad IO, bloquear toda la memoria direccionable, arrojan basura a través de /proc, /dev, /sys, LAN/Wi-Fi, ioctls firmware y de memoria flash de forma simultánea, overclock/sobrevoltaje de la CPU/GPU/RAM, y tiene una buena posibilidad de salir causando algo cercano a Halt and Catch Fire.

Si el proceso solo necesita hacer violencia metafórica, podría detenerse en /proc/sysrq-trigger.

Cuestiones relacionadas