2011-05-24 26 views
51

Estoy tratando de comprender cómo CTRL + C finaliza un proceso secundario pero no primario. Veo este comportamiento en algunos shells de script como bash donde puede iniciar algún proceso de larga ejecución y luego terminarlo ingresando CTRL - C y el control vuelve al shell.¿Cómo finaliza Ctrl-C un proceso hijo?

¿Podría explicarnos cómo funciona y, en particular, por qué no termina el proceso principal (shell)?

¿La cáscara tiene que hacer un manejo especial de CTRL +C evento y en caso afirmativo qué es exactamente lo que hace?

+1

¿Por qué terminar un hijo terminar el padre? Y no, no se necesita un manejo especial. –

+3

@Neil Butterworth: No estoy preguntando por qué dar de baja a un niño no está terminando a un padre. La pregunta es más ¿por qué el proceso secundario obtiene el evento Ctrl-C y no el padre? – vitaut

Respuesta

48

Las señales por defecto son manejadas por el núcleo. Los viejos sistemas Unix tenían 15 señales; ahora tienen más. Puede marcar </usr/include/signal.h> (o matar -l). CTRL + C es la señal con el nombre SIGINT.

La acción predeterminada para manejar cada señal se define también en el kernel, y generalmente termina el proceso que recibió la señal.

Todas las señales (pero SIGKILL) pueden manejarse por programa.

Y esto es lo que hace la cáscara:

  • Cuando la cáscara se ejecuta en modo interactivo, tiene una dirección para este modo de señal especial.
  • Cuando se ejecuta un programa, por ejemplo find, la cáscara:
    • fork sí s
    • y para el niño ajustar la señal por defecto manejo
    • reemplazar al niño con el comando dado (por ejemplo, con el hallazgo)
    • cuando se presiona CTRL + C, shell padre manejar esta señal, pero el niño recibirá - con la acción por defecto - por terminado. (El niño puede poner en práctica el manejo de señales demasiado)

Puede trap señales en la secuencia de comandos shell demasiado ...

y se puede establecer la señal de manipulación para su consola interactiva también, intentar introducir esto en la parte superior de ti ~/.profile. (Asegúrese de que usted está una que ya ha entrado en y probarlo con otro terminal - se puede bloquear a sí mismo)

trap 'echo "Dont do this"' 2 

Ahora, cada vez que se pulsa CTRL +C en su concha, se imprimirá un mensaje. ¡No te olvides de quitar la línea!

Si está interesado, puede verificar el viejo manejo de señales /bin/sh en el código fuente here.

En el anterior había algunas desinformaciones en los comentarios (ahora eliminadas), por lo que si alguien interesado aquí es un enlace muy bueno - how the signal handling works.

+1

Gracias por la explicación y por el enlace. "TTY desmitificado" es una de las mejores presentaciones que he visto. – vitaut

+3

SIGSTOP también es inalcanzable. –

+1

* cuando presiona 'CTRL + C', el shell primario maneja esta señal * - esto es completamente incorrecto ya que el shell ni siquiera recibe esta señal en este escenario; ver @ JdeBP's [respuesta] (http://stackoverflow.com/a/6110213/95735). –

7

El terminal envía la señal INT (interrupción) al proceso que está actualmente conectado al terminal. El programa luego lo recibe y puede optar por ignorarlo o salir.

Ningún proceso necesariamente se cierra a la fuerza (aunque de manera predeterminada, si no maneja sigint, creo que el comportamiento es llamar al abort(), pero tendré que buscarlo).

Por supuesto, el proceso de ejecución está aislado del shell que lo lanzó.

Si querían el shell padre para ir, poner en marcha su programa con exec:

exec ./myprogram 

De esta manera, el shell padre se sustituye por el proceso hijo

+0

¿Entiendo correctamente que cuando comienzo algún proceso desde un shell, se conecta al terminal y es por eso que recibe la señal INT? – vitaut

+1

Normalmente, sí. Para trabajos en primer plano en shell popular, sí. Dependerá del caparazón y de si existe una terminal. – sehe

+1

@kobame: ¿Entonces está diciendo que la señal se envía primero al shell que luego lo pasa al proceso hijo? ¿Por qué entonces enviar el SIGINT manualmente al shell no mata al niño, p. 'kill -2 ' no le hace nada a un proceso secundario mientras Ctrl-C lo mata? – vitaut

3

CTRL + C es un mapa del comando kill. Cuando los presionas, kill envía una señal SIGINT, eso interrumpe el proceso.

muertes: http://en.wikipedia.org/wiki/Kill_(command)

SIGINT: http://en.wikipedia.org/wiki/SIGINT_(POSIX)

+1

Gracias por los enlaces, pero ¿cómo se determina el proceso objetivo para la señal SIGINT? ¿Y quién implementa el mapeo, el caparazón mismo? – vitaut

+1

El proceso objetivo es el proceso actual que está ejecutando. La asignación se establece en la terminal, puede cambiarla con stty. –

+1

Otro enlace: http://www.devdaily.com/unix/edu/IntroToUnix/node4.shtml#SECTION004120000000000000000 –

19

Primero, lea the Wikipedia article on the POSIX terminal interface hasta el final.

La señal SIGINT es generada por la disciplina de la línea de terminal, y se transmite a todos los procesos en el grupo de proceso en primer plano de la terminal. Su shell ya ha creado un nuevo grupo de procesos para el comando (o canalización de comandos) que ejecutó, y le dijo al terminal que ese grupo de procesos es su (el terminal) grupo de procesos en primer plano. Cada canalización de comandos simultáneos tiene su propio grupo de procesos, y la línea de comandos en primer plano es la que tiene el grupo de procesos que el shell ha programado en el terminal como grupo de procesos en primer plano del terminal. Cambiar de "trabajos" entre primer plano y fondo es (algunos detalles a un lado) una cuestión de que el shell le dice al terminal qué grupo de proceso es ahora el primero.

El proceso de shell en sí mismo está en otro grupo de procesos propio y por lo tanto no recibe la señal cuando uno de esos grupos de procesos está en primer plano. Es así de simple.

Cuestiones relacionadas