2.1.6 Apéndice I: Multiprogramación y tiempo compartido
La mayoría de los sistemas operativos utilizan una técnica de gestión del procesador denominada multiprogramación, o una variante de ésta llamada tiempo compartido. Los primeros sistemas operativos gestionaban el procesador mediante otra técnica llamada monoprogramación (utilizada en los monitores de batch de flujo único). En este apartado comentaremos el por qué se evolucionó de la monoprogramación a la multiprogramación. Antes de entrar en esta discusión vamos a ver cómo se realizan las operaciones de entrada/salida (E/S), es decir, las operaciones que permiten la comunicación con los dispositivos de E/S.
Realización de las operaciones de E/S
Para facilitar el uso de los dispositivos, éstos se dividen en dos componentes. La primera es la componente eléctrica, a la cual se le llama controlador del dispositivo. La segunda es la componente mecánica, y es a lo que se llama propiamente dispositivo. Esta división permite un diseño más modular del dispositivo, además de simplificar su uso, ya que la CPU casi siempre trabaja con el controlador (más fácil de usar), que hace de interfaz entre la CPU y el dispositivo.
El controlador contiene una serie de registros llamados puertos de entrada/salida. Estos registros son accesibles (pueden ser leídos y modificados) mediante la ejecución de instrucciones máquina. Las operaciones de E/S se realizan a través de la carga y lectura de estos registros. Casi todo controlador dispone de los siguientes registros:
Registro de estado. Indica la situación actual del dispositivo. Un bit del registro, al que llamaremos bit de ocupación, indica si el dispositivo está ocupado (el bit tendrá el valor uno) realizando una operación de E/S o si está desocupado (el bit tendrá el valor cero), y, por tanto, preparado para recibir una orden.
Registro de órdenes. En este registro se escribe la operación de E/S que se desea que realice el dispositivo. Por ejemplo, en una cinta un código de 00 puede indicar rebobinar la cinta, 01 leer de la cinta, 10 escribir en la cinta, etc. El controlador se encarga de traducir estas órdenes en órdenes comprensibles para el dispositivo.
Buffer. Un buffer es un almacén de información. El buffer del controlador se utiliza para guardar temporalmente los datos implicados en una operación de E/S. Por ejemplo, si se quiere escribir en una impresora, se carga la información a escribir desde memoria principal al buffer. Posteriormente, el controlador mandará dicha información desde el buffer a la impresora.
Pasemos ahora a introducir el concepto de monoprogramación. En un sistema de monoprogramación todos los recursos del ordenador -CPU, memoria, discos, impresoras, etc- se dedican a la ejecución de un único programa. Este modo de trabajar lleva a una baja utilización de los recursos del ordenador como se justifica a continuación. Cuando el programa en ejecución realiza una operación de E/S se introduce la orden precisa en el registro de órdenes. El controlador responde a esto traduciendo esas órdenes al dispositivo, y poniendo a uno el bit de ocupación para indicar que el dispositivo está ocupado realizando una operación de E/S. Cuando termine la operación, el controlador pone a cero este bit para indicar que la operación concluyó, y el dispositivo está desocupado. Para saber cuándo termina la E/S, el programa, después de mandar la orden, tiene que ejecutar un ciclo del siguiente estilo:
Leer el registro de estado
Mientras (el bit de ocupación esté a uno)
Leer el registro de estado
Fin Mientras
Figura 6.1 Utilización de los recursos con monoprogramación
Obsérvese que esta forma de realizar las operaciones de E/S nos lleva a una situación en la que en un momento dado se tiene que, o bien la CPU está ejecutando instrucciones de un programa que no son de E/S, y los dispositivos de E/S están ociosos, o bien un único dispositivo de E/S está trabajando, mientras la CPU está en un ciclo comprobando si ha finalizado la operación. Esto se ilustra en la figura 6.1, donde los rectángulos rellenos a trazas representan el ciclo de comprobación. Para dar una medida de la infrautilización de los recursos que conlleva esta forma de realizar las E/S, piénsese que en el tiempo en que una impresora imprime una línea, la CPU, en lugar de ejecutar el ciclo de comprobación que aparece líneas más arriba, podría ejecutar millones de instrucciones de otro programa. A esta forma de realizar la E/S de los sistemas de monoprogramación se le llama E/S controlada por programa.
Para paliar la baja utilización de los recursos se desarrolló la multiprogramación. La multiprogramación se apoya en varios elementos del hardware: la interrupción, el DMA y el canal. En un sistema multiprogramado la memoria principal alberga a más de un programa de usuario. La CPU ejecuta instrucciones de un programa, cuando el programa en ejecución (es decir, el que ocupa la CPU) realiza una operación de E/S, emite ciertas órdenes al controlador (al igual que en los sistemas monoprogramados); pero en lugar de esperar a que termine la operación de E/S comprobando el bit de ocupación, se pasa a ejecutar otro programa. Si este nuevo programa realiza, a su vez, otra operación de E/S, se mandan las órdenes oportunas al controlador, y pasa a ejecutarse otro programa. Esto permite que varios dispositivos trabajen simultáneamente, además, en la CPU no se tienen que ejecutar ciclos de comprobación del estado de los dispositivos.
Esto se ilustra en la figura 6.2, en ella P1, P2 y P3 representan programas que residen en la memoria principal. Los rectángulos representan si el recurso está siendo utilizado, salvo para P1, P2 y P3 que representan si el programa ocupa la CPU. Al principio se está ejecutando P1, cuando inicia una operación de E/S con la impresora se cede la CPU a P2. P2 se ejecuta hasta que comienza una operación con el scanner, entonces se cede la CPU a P3, éste se ejecuta hasta que utiliza la impresora, momento en el cual se reanuda P1. Obsérvese que en este ejemplo la CPU siempre está activa. No obstante, podría suceder que todos los programas que residen en la memoria inicien una operación de E/S y en un momento dado todos estén esperando la finalización de su operación, esto conllevaría la no utilización de la CPU hasta que acabe la operación de E/S de cualquiera de los programas.
Figura 6.2 Utilización de los recursos con multiprogramación
Cuando un dispositivo acaba una operación de E/S debe de poder comunicárselo al programa que espera su finalización, para que así, el programa pueda proseguir su ejecución. Para indicar el fin de la operación el controlador manda una interrupción a la CPU. Una interrupción no es más que una señal eléctrica que provoca que el contador del programa y la PSW del programa en ejecución se salven en un lugar seguro de memoria, para, a continuación, cargar el contador de programa con una dirección fija de memoria donde reside un programa del sistema operativo que gestiona la interrupción. Este programa ejecutará cierto código para indicar al programa que esperaba la finalización de la operación de E/S que ésta ya terminó. Una vez que este programa del sistema operativo acaba su trabajo ejecuta una instrucción de retorno de interrupción, la cual restaura el contador de programa y la PSW del programa interrumpido, prosiguiéndose así su ejecución sin que éste sea consciente de que ha sido interrumpido. A esta forma de realizar la E/S se le llama E/S controlada por interrupción.
Analicemos ahora el DMA y el canal. Cuando un dispositivo realiza una operación de E/S, por ejemplo, una lectura de una cinta, la información leída pasa al buffer del controlador. Después, el programa que inició la lectura ejecuta ciertas instrucciones para copiar esta información desde el buffer hacia la memoria principal. La copia se realiza mediante un ciclo, copiando en cada iteración del ciclo un byte o una palabra desde el buffer del controlador a la memoria principal. En un controlador que disponga de DMA (acrónimo de Direct Memory Access, acceso directo a memoria) la copia del buffer a memoria la realiza el propio controlador; para ello, el programa ha de indicarle al controlador la dirección de memoria de inicio de la copia y el número de bytes a copiar, esto lo hace en el momento de darle la orden de E/S, metiendo esta información en algunos registros del controlador. Pasemos ahora a ver lo que es un canal, un canal es un pequeño procesador de E/S (es decir, un ordenador que sólo entiende instrucciones de E/S), su utilidad es proporcionar DMA a varios dispositivos, resultando más económico que tener un controlador DMA por dispositivo.
Después de la aparición de la multiprogramación surgieron los ordenadores de acceso múltiple o multiusuario. En ellos cada usuario dispone de un terminal, es decir, un teclado y una pantalla conectados al ordenador. Los usuarios ejecutan programas interactivos. Un programa interactivo es aquel que se comunica con el usuario por medio de un terminal, el usuario le suministra información al programa mediante el teclado, y recibe información del programa a través de la pantalla. Los programas de los usuarios comparten los recursos (CPU, memoria, discos, impresoras, etc) del ordenador. Estos sistemas hacen uso de una variante de la multiprogramación llamada tiempo compartido.
En el tiempo compartido los programas de los distintos usuarios residen en memoria; al realizar una operación de E/S los programas ceden la CPU a otro programa, al igual que en la multiprogramación. Pero, a diferencia de ésta, cuando un programa lleva cierto tiempo ejecutándose sin realizar operaciones de E/S el sistema operativo lo detiene para que se ejecute otro programa. Con esto se consigue repartir la CPU con equidad entre los programas de los distintos usuarios. Al tener la CPU una capacidad de cálculo tan grande, los programas de los usuarios no se sienten demasiado ralentizados por el hecho de que la CPU (y los demás recursos) sean compartidos.
Definamos ahora el término concurrencia. Por concurrencia se entiende la existencia de varias actividades simultáneas o paralelas. Ejemplo de ello lo constituyen la superposición de las operaciones de E/S con el proceso de computación. Otro ejemplo lo constituye la concurrencia de varios programas que se conmutan en un procesador. Aunque esta concurrencia no es real en un instante dado (si sólo existe un procesador), sí es real en un intervalo más amplio de tiempo.
En general, a lo largo del curso estudiaremos sistemas operativos que se ejecutan sobre un único procesador. Los sistemas distribuidos prácticamente no se tendrán en cuenta. Cuando se hable de algo aplicable a un sistema multiprocesador (memoria compartida) se observará explícitamente.