En este apartado se va a comentar cómo han ido evolucionando
los sistemas operativos a través de la historia. No estamos interesados en las
fechas, sino en la progresión de las ideas.
En un principio no existían sistemas operativos, programándose
sobre el hardware básico. Los programas se escribían en lenguaje máquina, y
se introducían en el ordenador, junto a los datos, en octal o hexadecimal
mediante una consola con
interruptores manuales. Se iniciaban los programas cargando el registro contador
de programa con la dirección de memoria de la primera instrucción del programa.
Los resultados de la ejecución se obtenían examinando el contenido de los registros y posiciones de
memoria relevantes. Los dispositivos de E/S se controlaban directamente,
escribiendo y leyendo en los puertos de E/S.
Evidentemente la programación del hardware básico
resulta baja en productividad, tanto para los usuarios, como para la máquina. El
proceso largo y tedioso de la introducción de programas y datos excluye
prácticamente la ejecución de programas medios y grandes.
Un siguiente paso significativo en la evolución en el uso de
los ordenadores viene con la llegada de los dispositivos de E/S, tales como
lectores de tarjetas y de cintas de papel perforadas. También aparecen los traductores de lenguajes.
Los programas, codificados ahora en un lenguaje simbólico, se traducen a forma
ejecutable mediante un traductor. Otro programa, llamado cargador, automatiza la
carga de programas ejecutables en memoria. El usuario pone un programa y sus
datos de entrada en un dispositivo de entrada, y el cargador transfiere
información desde el dispositivo de entrada a memoria. Después, se transfiere el
control, mediante medios manuales o automáticos, al programa cargado para su
ejecución. El programa en ejecución lee sus entradas desde el dispositivo de
entrada designado y puede producir alguna salida en un dispositivo de salida,
como la impresora o la pantalla. Una vez en memoria, el programa se puede
reejecutar con un conjunto diferente de datos de entrada.
El mecanismo de desarrollo de programas sigue siendo engorroso.
En una secuencia típica, se carga el programa editor para preparar el código
fuente del programa de usuario. El siguiente paso es cargar y ejecutar el
traductor, y alimentarlo con el código fuente del programa de usuario. Los
traductores de paso múltiple pueden requerir que se vuelva a poner el código
fuente durante cada paso para leerlo. Una vez corregido sintácticamente el
programa se ejecuta el código objeto. Si se detectan errores en la ejecución, se
puede examinar y modificar el contenido de la máquina mediante los interruptores
de la consola, o con la ayuda de un programa denominado depurador.
La mayoría de los programas utilizaban dispositivos de E/S. Una
mejora lógica fue el proporcionar unas rutinas estándares de E/S que fueran
usadas por todos los programas. Al principio, las rutinas de E/S se
introducían con las demás tarjetas del programa de usuario. Posteriormente, se
guardaba en memoria las rutinas compiladas, y mediante un programa enlazador se combinaban con
el código objeto del usuario.
En estos sistemas las rutinas de E/S y el programa cargador
constituyen una forma rudimentaria de sistema operativo. Los traductores, editores y depuradores son programas
de sistema, pero no forman parte del sistema operativo.
Hasta ahora la utilización del procesador es muy baja, pues el
tiempo empleado en leer un programa almacenado en tarjetas suele ser mucho
mayor que el empleado en ejecutar el programa. Cuando aparecieron las cintas
magnéticas, cuya lectura y escritura era muy inferior en tiempo a las tarjetas,
se pensó que se utilizaría más el procesador si todas las entradas y salidas se
realizaban sobre cintas.
Para realizar esto se utilizó una técnica de
off-lining (fuera de línea). La idea era dedicar un
ordenador periférico, de menor costo y potencia, a convertir las tarjetas o la
cinta perforada en información sobre cinta magnética, y la salida sobre cinta
magnética en salida sobre impresora o cinta perforada. Una vez que se procesaban
varios trabajos a cinta, ésta se desmontaba del ordenador periférico, y se
llevaba a mano para su procesamiento por el ordenador principal. Cuando el
ordenador principal llenaba una cinta de salida, ésta se llevaba al ordenador
periférico para su paso a impresora o cinta perforada.
Una de las implicaciones de esta forma de trabajo era que en
una cinta de entrada podían existir los trabajos de varios programadores. Para
diferenciar los trabajos (o tareas) de distintos programadores se
introducían tarjetas de control que interpretaba un sistema operativo
embrionario. Así, por ejemplo, un trabajo podía empezar con una tarjeta $JOB de
comienzo, con un identificativo del programador. Después una tarjeta $FORTRAN
para indicarle al sistema operativo que cargue el compilador de FORTRAN de una
cinta del sistema. A continuación vendrían las tarjeta del código fuente. Una
tarjeta $LOAD para que se cargue en memoria el programa compilado (pues
usualmente se guardaba en cinta). La tarjeta $RUN indicaba que se ejecutara el
programa con los datos que vienen en las tarjetas siguientes. Por fin, una
tarjeta $END indicaba el fin del trabajo.
El sistema operativo residía en memoria y tenía un programa de
control que interpretaba las tarjetas de control, las cuales representaban un
lenguaje de control de tareas. Dependiendo del tipo de tarjeta de control
el sistema operativo realizaba una acción determinada. Este programa de control
es un antecedente de los modernos intérpretes de órdenes.
Con esta forma de trabajo el programador entregaba sus
tarjetas a un operador y esperaba horas hasta que el programa proporcionara su
salida. La falta de un punto y coma al final de una línea de un programa podía
provocar un error sintáctico, y la pérdida de estas horas de espera. Por otro
lado, debido a que la cinta magnética es un medio de almacenamiento serie, no había opción alguna
de orden de ejecución de las tareas que no fuese el orden en que éstas se habían
presentado al ordenador.
De cara a eliminar la dependencia de las E/S en lugar de tan
sólo reducirla, hay que emplear técnicas mediante las cuales se puedan
superponer las E/S al proceso a ejecutar. Ello es posible con la ayuda de dos
elementos del hardware: el canal
y la interrupción. Un canal es un elemento que controla uno o más
dispositivos, llevando a cabo transferencias de datos entre estos dispositivos y
la memoria sin involucrar prácticamente al procesador central. Una interrupción es una
señal que transfiere el control del procesador central a una posición fija de
memoria, almacenando al mismo tiempo el valor anterior del contador de programa,
y, posiblemente, la palabra de estado
del procesador. De esta forma, se suspende temporalmente la ejecución del
programa que estaba siendo llevado a cabo en el momento de la interrupción,
aunque podrá reemprenderse dicha ejecución más tarde (o sea, el programa es
interrumpido). Una interrupción de un canal actúa como señal que indica
que se ha completado una transferencia de datos. De esta forma es posible que el
procesador central inicie una transferencia a un dispositivo, continúe el
proceso que estaba llevando a cabo mientras el canal controla la transmisión y
reciba a través de una interrupción la notificación de haberse completado dicha
transferencia.
Es posible ahora leer las tareas a ejecutar guardándolas en un
soporte adecuado (normalmente disco), y ejecutarlas una a una al mismo tiempo
que se van leyendo otras. Para ello ha habido que añadir a nuestro sistema
operativo una rutina de gestión de las interrupciones y otra que decida cuál de
las tareas almacenadas en disco será la siguiente en ser ejecutada. Esta última
función, que recibe el nombre de sheduling, deriva del
empleo del disco (caracterizado por un acceso aleatorio) como medio de
almacenamiento de las distintas tareas en lugar de la cinta magnética,
caracterizada por un acceso serie. Un sistema que trabaje de esta forma recibe
el nombre de monitor de batch de flujo único (en
inglés, single stream batch monitor). El concepto de flujo único lleva
implícita la idea de una sóla tarea ejecutándose a la vez.
La principal desventaja de un sistema de cola única es la total
dedicación de la máquina a la ejecución de una sóla tarea, no importa lo larga o
lo corta que sea. Este inconveniente puede superarse mediante la multiprogramación,
o sea, la ejecución simultánea de varios programas que residen en la memoria
principal, dividiendo el procesador central su tiempo entre ellos de acuerdo con
los recursos (tal como canales o dispositivos) que necesite en cada momento cada
uno de ellos. De esta forma es posible, teniendo almacenado un conjunto adecuado
de tareas en cada momento, obtener una utilización óptima de los recursos
disponibles. Ello incluye la utilización del procesador central, ya que en tanto
que una tarea esté esperando el final de una transferencia de E/S, este
procesador puede pasar a trabajar en alguna otra tarea que esté pendiente en la
máquina. La carga que recae sobre el sistema operativo consiste en el control de
los recursos, así como la protección de cada tarea frente a las actividades de
las otras. Un sistema operativo de este tipo recibe el nombre de monitor de
batch de varios
flujos.
En el estadio actual de la progresión que hemos llevado a cabo
tenemos un sistema notablemente sofisticado que hace bastante buen uso de la
electrónica disponible. Sin embargo, desde el punto de vista del usuario el
sistema adolece de falta de interactividad, tan
necesaria en el proceso de desarrollo de programas, y útil también para
desarrollar programas interactivos que respondan instantáneamente a las
peticiones del usuario. Para hacer posible esta interacción, el sistema de
batch de varios flujos debe modificarse con el fin de que pueda adquirir
la información que le suministren los usuarios desde los respectivos terminales:
es decir, debe convertirse en un sistema multiusuario. Un sistema
de este tipo, en el cual existen varios usuarios con un terminal en línea
(usuarios interactivos), se llama sistema de tiempo compartido.
En estos sistemas se divide el tiempo del procesador central, y de los demás
recursos del ordenador, de forma que cada usuario tiene la ilusión de que todo
el ordenador se le dedica exclusivamente a él, al recibir unos tiempos de
respuesta aceptables. En un sistema de tiempo compartido los usuarios suelen
ejecutar programas cortos (por ejemplo, compilar un programa), frente a los
programas largos (por ejemplo, ordenar una cinta de un millón de datos) que se
suelen dar en los sistemas batch.
Por último hay que indicar que algunos sistemas operativos
permiten tanto usuarios interactivos como lotes de trabajos batch. En
estos sistemas se atiende a los usuarios interactivos con mayor prioridad,
ejecutándose los programas batch cuando no hay programas de usuario.
En una red de ordenadores se tiene una configuración de varios
ordenadores conectados físicamente. Los ordenadores de una red pueden tener sistemas operativos de red o sistemas operativos distribuidos.
En un sistema operativo de red los usuarios son conscientes de
la existencia de varios ordenadores, y pueden conectarse con máquinas remotas
para, por ejemplo, copiar ficheros. Cada máquina ejecuta su propio sistema
operativo local y tiene su propio usuario (o grupo de usuarios). Los sistemas
operativos de red no difieren de los sistemas operativos tradicionales de un
sólo procesador. Necesitan un controlador de red, algunas rutinas de E/S para
utilizar dicho controlador, y programas que permitan la conexión y el acceso a
ordenadores remotos, pero esas características adicionales no modifican la
estructura esencial del sistema operativo.
En un sistema distribuido los ficheros que utiliza un usuario
(así como el procesador en el que se ejecutan sus programas) pueden estar
situados en cualquier ordenador de la red. Además, esto es transparente al
usuario. Los sistemas operativos distribuidos requieren algo más que añadir un
poco de código a un sistema operativo de un único procesador, ya que los
sistemas distribuidos difieren en aspectos críticos de los sistemas
centralizados.
No hay comentarios:
Publicar un comentario