¿Cómo se maneja una interrupción en Linux?

35

Solo sé que Interruptes una hardware signal assertioncausa en un pin del procesador. Pero me gustaría saber cómo lo maneja el sistema operativo Linux.
¿Cuáles son todas las cosas que suceden cuando ocurre una interrupción?

Sen
fuente
tldp.org/LDP/tlk/dd/interrupts.html explica todo sobre la pregunta que ha formulado
John

Respuestas:

40

Aquí hay una vista de alto nivel del procesamiento de bajo nivel. Estoy describiendo una arquitectura típica simple, las arquitecturas reales pueden ser más complejas o diferentes en formas que no importan a este nivel de detalle.

Cuando ocurre una interrupción , el procesador mira si las interrupciones están enmascaradas. Si lo son, no pasa nada hasta que se desenmascaran. Cuando las interrupciones se desenmascaran, si hay interrupciones pendientes, el procesador elige una.

Luego, el procesador ejecuta la interrupción ramificándose a una dirección particular en la memoria. El código en esa dirección se llama controlador de interrupciones . Cuando el procesador se bifurca allí, enmascara las interrupciones (por lo que el controlador de interrupciones tiene control exclusivo) y guarda el contenido de algunos registros en algún lugar (generalmente otros registros).

El manejador de interrupciones hace lo que debe hacer, generalmente comunicándose con el periférico que activó la interrupción para enviar o recibir datos. Si el temporizador provocó la interrupción, el controlador podría activar el programador del sistema operativo para cambiar a un hilo diferente. Cuando el controlador termina de ejecutarse, ejecuta una instrucción especial de retorno de interrupción que restaura los registros guardados y desenmascara las interrupciones.

El controlador de interrupciones debe ejecutarse rápidamente, ya que impide que se ejecute cualquier otra interrupción. En el kernel de Linux, el procesamiento de interrupción se divide en dos partes:

  • La "mitad superior" es el controlador de interrupciones. Hace lo mínimo necesario, normalmente se comunica con el hardware y establece un indicador en algún lugar de la memoria del kernel.
  • La "mitad inferior" realiza cualquier otro procesamiento necesario, por ejemplo, copiar datos en la memoria de proceso, actualizar las estructuras de datos del kernel, etc. Puede tomar su tiempo e incluso bloquear la espera de alguna otra parte del sistema, ya que se ejecuta con interrupciones habilitadas.

Como es habitual en este tema, para obtener más información, lea Controladores de dispositivo Linux ; El capítulo 10 trata sobre las interrupciones.

Gilles 'SO- deja de ser malvado'
fuente
22

Gilles ya describió el caso general de una interrupción, lo siguiente se aplica específicamente a Linux 2.6 en una arquitectura Intel (parte de esto también se basa en las especificaciones de Intel).

Una interrupción es un evento que cambia la secuencia de instrucciones ejecutadas por el procesador.
Hay dos tipos diferentes de interrupciones:

  • Interrupción síncrona (excepción) producida por la CPU al procesar instrucciones
  • Interrupción asincrónica (interrupción) emitida por otros dispositivos de hardware

Las excepciones son causadas por errores de programación (por ejemplo , error de división , error de página , desbordamiento ) que debe manejar el núcleo. Envía una señal al programa e intenta recuperarse del error.

Se clasifican las siguientes dos excepciones:

  • Excepción detectada por el procesador generada por la CPU al detectar una condición anómala; dividido en tres grupos: las fallas generalmente se pueden corregir, las trampas informan una ejecución, los abortos son errores graves.
  • Excepción programada solicitada por el programador, manejada como una trampa.

Las interrupciones pueden ser emitidas por dispositivos de E / S (teclado, adaptador de red, ..), temporizadores de intervalo y (en sistemas multiprocesador) otras CPU. Cuando ocurre una interrupción, la CPU debe detener su instrucción actual y ejecutar la interrupción recién llegada. Necesita guardar el antiguo estado del proceso interrumpido para (probablemente) reanudarlo después de que se maneje la interrupción.

Manejar interrupciones es una tarea delicada:

  • Las interrupciones pueden ocurrir en cualquier momento, el núcleo trata de eliminarlo lo antes posible
  • Una interrupción puede ser interrumpida por otra interrupción
  • Hay regiones en el núcleo que no deben interrumpirse en absoluto.

Se definen dos niveles de interrupción diferentes:

  • Interrupciones enmascaradas emitidas por dispositivos de E / S; puede estar en dos estados, enmascarados o sin máscara. Solo se están procesando las interrupciones sin máscara.
  • Interrupciones no enmascarables ; fallos críticos (por ejemplo, falla de hardware); siempre procesado por la CPU.

Cada dispositivo de hardware tiene su propia línea de solicitud de interrupción (IRQ). Las IRQ están numeradas a partir de 0. Todas las líneas IRQ están conectadas a un controlador de interrupción programable (PIC). El PIC escucha las IRQ y las asigna a la CPU. También es posible deshabilitar una línea IRQ específica.
Los sistemas Linux multiprocesamiento modernos generalmente incluyen el nuevo PIC avanzado (APIC), que distribuye las solicitudes de IRQ por igual entre las CPU.

El paso intermedio entre una interrupción o excepción y su manejo es la Tabla de descriptores de interrupción (IDT). Esta tabla asocia cada vector de interrupción o excepción (un número) con un controlador específico (por ejemplo, la función maneja el error de divisióndivide_error() ).

A través del IDT, el núcleo sabe exactamente cómo manejar la interrupción o excepción ocurrida.


Entonces, ¿qué hace el núcleo cuando ocurre una interrupción?

  • La CPU verifica después de cada instrucción si hay una IRQ del PIC (A)
  • Si es así, consulta el IDT para asignar el vector recibido a una función
  • Comprueba si la interrupción fue emitida por una fuente autorizada
  • Guarda los registros del proceso interrumpido
  • Llame a la función correspondiente para manejar la interrupción
  • Cargue los registros guardados recientemente del proceso interrumpido e intente reanudarlo
meneo
fuente
¿Puede aclarar "La CPU verifica después de cada instrucción si hay una IRQ del (A) PIC" . ¿Cómo sucede exactamente? ¿Se relaciona con VIP-flag en el registro de banderas o lo que sea? Gracias de antemano
red0ct
7

En primer lugar, los participantes involucrados en el manejo de interrupciones son dispositivos de hardware periférico, controlador de interrupciones, CPU, núcleo del sistema operativo y controladores. Los dispositivos de hardware periférico son responsables de la generación de interrupciones. Afirman líneas de solicitud de interrupción cuando quieren atención del núcleo del sistema operativo. Estas señales son multiplexadas por el controlador de interrupción, que es responsable de la recolección de señales de interrupción. También es responsable de determinar el orden en que las señales de interrupción se pasarán a la CPU. El controlador de interrupción puede deshabilitar temporalmente una línea de solicitud de interrupción particular (IRQL) y volver a habilitarla nuevamente (enmascaramiento IRQL). El controlador de interrupción pasa las solicitudes de interrupción recopiladas a la CPU de forma secuencial. La CPU después de completar la ejecución de cada instrucción La CPU verifica si hay alguna solicitud de interrupción en espera del controlador de interrupción. Si la CPU encuentra que hay una solicitud de espera Y el indicador de habilitación de interrupción se establece en el registro de control interno de la CPU, la CPU comienza a manejar la interrupción. Como puede ver, al manipular el indicador de interrupción en la CPU y comunicarse con el controlador de interrupción, el kernel de Linux puede controlar la aceptación de la interrupción. Por ejemplo, Linux puede deshabilitar la aceptación de interrupciones desde un dispositivo en particular o deshabilitar la aceptación de interrupciones. El kernel de Linux puede controlar la aceptación de interrupciones. Por ejemplo, Linux puede deshabilitar la aceptación de interrupciones desde un dispositivo en particular o deshabilitar la aceptación de interrupciones. El kernel de Linux puede controlar la aceptación de interrupciones. Por ejemplo, Linux puede deshabilitar la aceptación de interrupciones desde un dispositivo en particular o deshabilitar la aceptación de interrupciones.

¿Qué sucede cuando el procesador recibe una solicitud de interrupción? En primer lugar, la CPU deshabilita automáticamente las interrupciones restableciendo el indicador de interrupción. Se volverán a habilitar una vez que finalice el manejo de interrupciones. Al mismo tiempo, la CPU realiza una cantidad mínima de trabajo necesaria para cambiar la CPU del modo de usuario al modo kernel de tal manera que le permita reanudar la ejecución del código interrumpido. La CPU consulta con estructuras especiales de control de la CPU llenadas por el kernel de Linux para encontrar una dirección de código a la que se pasará el control. Esta dirección es la dirección de la primera instrucción del controlador de interrupciones, que forma parte del núcleo de Linux.

Como primer paso para el manejo de interrupciones, el núcleo identifica el vector de interrupción recibido para identificar qué tipo de evento ha sucedido en el sistema. El vector de interrupción define qué acciones tomará Linux para manejarlo. Como segundo paso, Linux guarda el resto de los registros de la CPU (que la CPU no guardó automáticamente) y que potencialmente pueden ser utilizados por el programa interrumpido. Esta es una acción muy importante, ya que permite que Linux maneje las interrupciones de forma transparente con respecto al programa interrumpido. Como tercer paso, Linux logra cambiar al modo kernel configurando el entorno del kernel y el estado de la CPU requerido para ello. Y finalmente, se llama al controlador de interrupción dependiente del vector. (Puede buscar en la macro BUILD_INTERRUPT3 en arch \ x86 \ kernel \ entry_32. S para obtener detalles adicionales para el ejemplo relacionado con la arquitectura x86) En el caso de dispositivos periféricos, esta es una rutina do_IRQ (). (Mire dentro del arco \ x86 \ kernel \ irq.c)

El controlador de interrupción dependiente del vector generalmente envuelto por llamadas a irq_enter () e irq_exit (). El área de código encerrada dentro de un par de estas funciones es atómica con respecto a cualquier otra área y también es atómica con respecto a pares de cli / sti. Irq_enter () e irq_exit () también captura algunas estadísticas relacionadas con el manejo de interrupciones. Finalmente, el núcleo busca en la tabla vector_irq para encontrar el número irq asignado al vector de la interrupción recibida y llama a handle_irq () (desde arch \ x86 \ kernel \ irq_32.c).

En este punto, la parte común del manejo de interrupciones en Linux termina, porque el kernel considera la rutina de manejo de interrupciones dependiente del dispositivo instalada por el controlador del dispositivo como parte del descriptor irq y la invoca. Si dicho controlador no fue instalado por el controlador, el núcleo simplemente reconoce la interrupción en el controlador de interrupción y sale para salir del controlador de interrupción general.

Después del final del kernel de manejo de interrupciones, se restaura el estado del programa que se interrumpió anteriormente y se reanuda la ejecución de este programa.

ZarathustrA
fuente
CPU consults with special CPU control structures filled by Linux kernel to find an address of code to which control will be passed.¡Sí! Aunque me pregunto cuáles son esas estructuras de control especiales ...
autómata