Casi todos los computadores tienen un mecanismo mediante el cual otros módulos (E/S, memoria) pueden interrumpir la ejecución normal del procesador. La tabla 1.1 enumera las clases más comunes de interrupciones.
Clases de Interrupciones | |
De programa | Generadas por alguna condición que se produce como resultado de la ejecución de una instrucción, como el desbordamiento aritmético, la división por cero, el intento de ejecutar una instrucción ilegal de la máquina o una referencia a una zona de memoria fuera del espacio permitido al usuario. |
De reloj | Generadas por un reloj interno del procesador. Esto permite al sistema operativo llevar a cabo ciertas funciones con determinada regularidad. |
De E/S | Generadas por un controlador de E/S, para indicar que una operación ha terminado normalmente o para indicar diversas condiciones de error. |
Por fallo del hardware | Generadas por fallos tales como un corte de energía o un error de paridad de la memoria. |
Las interrupciones aparecen, principalmente, como una vía para mejorar la eficiencia del procesamiento. Por ejemplo, la mayoría de los dispositivos externos son mucho más lentos que el procesador.
Supóngase que el procesador está transfiriendo datos hacia una impresora. Después de cada operación ESCRIBIR, el procesador hará una pausa y permanecerá desocupado hasta que la impresora haga su trabajo. La duración de esta pausa puede ser del orden de varios cientos o incluso miles de ciclos de instrucción en los que la memoria no está implicada. Está claro que esto es un derroche en la utilización del procesador.
La figura en la parte (a) ilustra este estado de las cosas para la aplicación que se indica en el párrafo anterior.
El programa de usuario lleva a cabo una serie de llamadas a ESCRIBIR, intercaladas con el procesamiento. Los segmentos de código 1, 2 y 3 se refieren a secuencias de instrucciones que no implican E/S.
Las llamadas a ESCRIBIR son, en realidad, llamadas a un programa de E/S, que es una utilidad del sistema que llevará a cabo la operación concreta de E/S.
El programa de E/S consta de tres secciones:
-
Una secuencia de instrucciones, etiquetada con un 4 en la figura, de preparación para la operación concreta de E/S.
Esto puede incluir la copia de los datos de salida hacia un buffer especial y preparar los parámetros de la orden del dispositivo.
-
La orden concreta de E/S. Sin el uso de interrupciones, una vez que se emita esta orden, el programa debe esperar a que el dispositivo de E/S lleve a cabo la función pedida. El programa puede esperar simplemente ejecutando de forma repetida una operación que compruebe si ya se realizó la E/S.
-
Una secuencia de instrucciones, etiquetada con un (5)
en la figura, para completar la operación. Esto puede incluir la activación de un código de condición que indique el éxito o el fracaso de la operación.
-
Debido a que la operación de E/S puede tardar un tiempo relativamente grande en terminar, el programa de E/S puede quedar colgado esperando a que se complete la operación; así pues, el programa de usuario se detendrá por un tiempo considerable en el momento de la llamada a ESCRIBIR.
Las interrupciones y el ciclo de instrucción
Con las interrupciones, el procesador se puede dedicar a la ejecución de otras instrucciones mientras una operación de E/S está en proceso.
Considérese el flujo de control de la figura (b). Al igual que antes, el programa de usuario alcanza un punto en el que hace una llamada al sistema en forma de una llamada ESCRIBIR. El programa de E/S que se invoca consta solo del código de preparación y de la orden concreta de E/S. Después de que se ejecuten estas pocas instrucciones, se devuelve el control al programa de usuario. Mientras tanto, el dispositivo externo estará ocupado recibiendo datos desde la memoria del computador e imprimiéndolos. Esta operación de E/S se lleva a cabo concurrentemente con la ejecución de las instrucciones del programa de usuario.
Cuando el dispositivo de E/S esté disponible, es decir, cuando esté preparado para aceptar más datos desde el procesador, el módulo de E/S de dicho dispositivo enviará una señal de solicitud de interrupción al procesador. El procesador responde suspendiendo la operación del programa en curso y saltando a un programa que da servicio al dispositivo de E/S en particular, conocido como rutina de tratamiento de la interrupción (interrupt handler), reanudando la ejecución original después de haber atendido al dispositivo. En La figura (b), el instante en que se produce tal interrupción viene indicado con un asterisco (*).
Desde el punto de vista del programa de usuario, una interrupción es solamente eso: una interrupción de la secuencia normal de ejecución. Cuando el tratamiento de la interrupción se termina, la ejecución continúa. Así pues, el programa de usuario no tiene que disponer de ningún código especial para dar cabida a las interrupciones; el procesador y el sistema operativo son los responsables de suspender el programa de usuario y reanudarlo después en el mismo punto.
Para dar cabida a las interrupciones, se añade un ciclo de interrupción al ciclo de instrucción, como se muestra en la próxima figura.
En el ciclo de interrupción, el procesador comprueba si ha ocurrido alguna interrupción, lo que se indicará con la presencia de una señal de interrupción. Si no hay interrupciones pendientes, el procesador sigue con el ciclo de lectura y trae la próxima instrucción del programa en curso. Si hay una interrupción pendiente, el procesador suspende la ejecución del programa en curso y ejecuta una rutina de tratamiento de la interrupción.
La rutina de tratamiento de la interrupción forma parte generalmente del sistema operativo. Normalmente este programa determina la naturaleza de la interrupción y realiza cuantas acciones sean necesarias. De hecho, en el ejemplo que se ha estado siguiendo, la rutina de tratamiento determina el módulo de E/S que generó la interrupción y puede saltar a un programa que escribirá más datos a dicho módulo. Cuando termina la rutina de tratamiento de la interrupción, el procesador puede reanudar la ejecución del programa de usuario en el punto en que sucedió la interrupción.
Está claro que hay cierta sobrecarga en este proceso. Se deben ejecutar instrucciones extra (en la rutina de tratamiento de la interrupción) para determinar la naturaleza de la interrupción y decidir la acción apropiada. Sin embargo, por la cantidad de tiempo que se desperdicia esperando en una operación de E/S, puede aprovecharse el procesador de una manera mucho más eficaz con el uso de interrupciones.
Tratamiento de interrupciones
El acontecimiento de una interrupción desencadena una serie de sucesos, tanto en el hardware del procesador como en el software.
Cuando un dispositivo de E/S completa una operación de E/S, se produce en el hardware la siguiente secuencia de sucesos:
1. El dispositivo emite una señal de interrupción al procesador.
2. El procesador finaliza la ejecución de la instrucción en curso antes de responder a la interrupción
3. El procesador pregunta por la interrupción, comprueba que hay una y envía una señal de reconocimiento al dispositivo que generó la interrupción. Este reconocimiento le permite al dispositivo suprimir la señal de interrupción.
4. El procesador necesita ahora prepararse para transferir el control a la rutina de interrupción. Para empezar, hace falta salvar la información necesaria para reanudar la ejecución del programa en curso en el punto de la interrupción. La mínima información requerida es la palabra de estado del programa (PSW) y la ubicación de la próxima instrucción a ejecutar, que se almacena en el contador de programa. Estos pueden meterse en la pila de control del sistema.
5. El procesador carga ahora el contador de programa con la ubicación de entrada del programa de tratamiento de la interrupción. Dependiendo de la arquitectura del computador y del diseño del sistema operativo, puede haber un solo programa por cada tipo de interrupción, o uno por cada dispositivo y por cada tipo de interrupción. Si hay más de una rutina de tratamiento de interrupción, el procesador debe determinar a cuál invocar. Esta información pudiera estar incluida en la señal original de la interrupción, o el procesador debe preguntarle al dispositivo que creó la interrupción para obtener respuesta sobre la información que necesita.
Una vez que se ha cargado el contador de programa, el procesador procede con el próximo ciclo de instrucción, que comienza trayendo la próxima instrucción. Debido a que esta instrucción se determina por el contenido del contador de programa, el resultado es que el control se le transfiere al programa que trata la interrupción. La ejecución de este programa se traduce en las operaciones siguientes:
6. En este punto, el contador de programa y la PSW relativa al programa interrumpido han sido salvadas en la pila del sistema. Sin embargo, hay más información que es considerada parte del «estado» de ejecución del programa. En particular se necesita salvar el contenido de los registros del procesador ya que estos registros pudieran ser utilizados por la rutina de tratamiento de la interrupción. Así pues es necesario salvar todos estos valores más cualquier otra información sobre el estado. Normalmente la rutina de tratamiento de la interrupción comienza salvando en la pila el contenido de todos los registros. En el capítulo 3 se discute sobre otra información del estado que también puede que tenga que salvarse.
7. La rutina de tratamiento de la interrupción puede ahora proceder a procesar la interrupción. Esto incluirá un examen del estado de la información relativa a la operación de E/S o a cualquier otro evento que haya causado la interrupción. Esto puede también involucrar el envío adicional de órdenes o reconocimientos al dispositivo de E/S.
8. Cuando se completa el tratamiento de la interrupción, se recuperan de la pila los valores de los registros que se salvaron y se restauran los registros.
9. El acto final es restaurar los valores de la PSW y del contador de programa a partir de la pila. Como resultado, la próxima instrucción a ser ejecutada será del programa interrumpido previamente.
Es importante salvar toda la información sobre el estado del programa interrumpido para su reanudación posterior, porque la rutina de tratamiento de la interrupción no es una rutina llamada desde el programa. Por el contrario, la interrupción puede producirse en cualquier momento y por tanto en cualquier punto de la ejecución de un programa de usuario. Su ocurrencia es impredecible. Más aún, como se verá más adelante en esta sección, los dos programas pueden no tener nada en común y pueden pertenecer a dos usuarios diferentes.
Interrupciones múltiples
En la discusión anterior se ha analizado el acontecimiento de una sola interrupción. Sin embargo, supóngase que pueden producirse múltiples interrupciones. Por ejemplo, un programa puede estar recibiendo datos de una línea de comunicaciones e imprimiendo resultados. La impresora generará una interrupción cada vez que se completa una operación de impresión. El controlador de la línea de comunicaciones generará una interrupción cada vez que llega una unidad de datos. Esta unidad puede ser un solo carácter o un bloque, dependiendo de la naturaleza de las normas de comunicación. En cualquier caso, es posible que se produzca una interrupción del controlador de comunicaciones cuando se está procesando una interrupción de la impresora.
Hay dos enfoques para tratar las interrupciones múltiples. El primero es inhabilitar las interrupciones mientras se esté procesando una. Una interrupción inhabilitada quiere decir que el procesador ignorará la señal de interrupción. Si durante este tiempo se produce una interrupción, ésta generalmente quedará pendiente y será comprobada por el procesador después que éste habilite las interrupciones. De este modo, cuando un programa de usuario está ejecutándose y se produce una interrupción, se inhabilitan inmediatamente las interrupciones. Después de terminar la rutina que trata la interrupción, se habilitan las interrupciones antes de reanudar el programa de usuario y el procesador comprueba si se ha producido alguna interrupción adicional. Este enfoque es simple y elegante porque las interrupciones se tratan en un orden estrictamente secuencial.
La limitación de este enfoque es que no tiene en cuenta las prioridades relativas o necesidades críticas en tiempo. Por ejemplo, cuando llega una interrupción desde la línea de comunicaciones, se necesita atender ésta rápidamente para hacer sitio a nuevas entradas. Si el primer lote de entrada no ha sido aún procesado cuando llega el segundo, pueden perderse datos.
Un segundo enfoque es definir prioridades para las interrupciones y permitir que una interrupción de una prioridad más alta pueda interrumpir a la rutina de tratamiento de una interrupción de prioridad más baja.
Como ejemplo de este segundo enfoque, considérese un sistema con tres dispositivos de E/S: una impresora, un disco y una línea de comunicaciones, con prioridad creciente de 2,4 y 5, respectivamente. Un programa de usuario comienza en t = 0. En t= 10, se produce una interrupción de la impresora; la información del usuario se coloca en la pila del sistema y la ejecución continúa en la rutina de servicio de la interrupción (ISR, Interrupt Service Routine) de la impresora. Mientras esta rutina sigue ejecutándose, en t = 15, se produce una interrupción de comunicaciones. Como la línea de comunicaciones tiene una prioridad más alta que la impresora, la interrupción es atendida. La ISR es interrumpida, su estado se pone en la pila y la ejecución continúa en la ISR de comunicaciones. Mientras esta rutina está ejecutándose, se produce una interrupción del disco (t = 20). Debido a que esta interrupción es de más baja prioridad, queda retenida y la ISR de comunicaciones se ejecuta hasta el final.
Cuando se completa la ISR de comunicaciones (t = 25), se restaura el estado previo del procesador, lo que significa continuar ejecutando la ISR de la impresora. Sin embargo, antes de ejecutar una sola instrucción de esta rutina, el procesador atiende a la mayor prioridad de la interrupción del disco y transfiere el control a la ISR del disco. Sólo cuando se completa esta rutina (t = 35) se reanuda la ISR de la impresora. Cuando se termina esta última (t = 40), el control vuelve finalmente al programa de usuario.
Multiprogramación
Aún con el uso de interrupciones, puede que un procesador no esté aprovechado de una manera muy eficiente. Si el tiempo necesario para completar una operación de E/S es mucho mayor que el código del usuario entre llamadas de E/S (una situación habitual), entonces el procesador va a estar desocupado durante gran parte del tiempo. Una solución a este problema es permitir que varios programas de usuario estén activos a un mismo tiempo.
Supóngase, por ejemplo, que el procesador tiene que ejecutar dos programas. Uno de ellos es simplemente un programa que lee datos de la memoria y los saca por un dispositivo externo; el otro es una aplicación que supone una gran cantidad de cálculos. El procesador puede dar comienzo al programa de salida, enviar una orden ESCRIBIR al dispositivo exterrno y luego comenzar la ejecución de la otra aplicación.
Cuando el procesador tiene que tratar con una serie de programas, la secuencia en que estos se ejecutan dependerá de su prioridad relativa y de si están esperando una E/S. Cuando un programa es interrumpido y se transfiere el control a la rutina de tratamiento de la interrupción, una vez que ésta haya terminado, puede que no se devuelva el control inmediatamente al programa de usuario que estaba ejecutándose en el momento de la interrupción. En su lugar, el control puede transferirse a algún otro programa pendiente que tenga mayor prioridad. Finalmente, cuando tenga la prioridad más alta, se reanudará el programa de usuario que fue interrumpido. Esta situación de varios programas que se ejecutan por turnos se conoce como multiprogramación.