domingo, 15 de noviembre de 2015

SERVICIOS DE ENTRADA/SALIDA

Servicios de entrada/salida

La mayoría de los sistemas operativos modernos proporcionan los mismos servicios para trabajar con
dispositivos de entrada/salida que los que usan con los archivos. Esta equivalencia es muy beneficiosa ya
que proporciona a los programas independencia del medio con el que trabajan. Así, para acceder a un
dispositivo se usan los típicos servicios para abrir, leer, escribir y cerrar archivos.
Sin embargo, en ocasiones es necesario poder realizar desde un programa alguna operación dependiente del
dispositivo. Por ejemplo, suponga un programa que desea solicitar al usuario una contraseña a través del
terminal. Este programa necesita poder desactivar el eco en la pantalla para que no pueda verse la contrasefia mientras se teclea. Se requiere, por tanto, algún mecanismo para poder
realizar este tipo de operaciones dependiendo del dispositivo. Existen al menos dos posibilidades no
excluyentes:
• Permitir que este tipo de opciones se puedan especificar como indicadores en el propio servicio
para abrir el dispositivo.
• Proporcionar un servicio que permita invocar estas opciones dependientes del dispositivo.

Servicios de entrada/salida en POSIX

Debido al tratamiento diferenciado que se da al reloj, se presentan separadamente los servicios relacionados
con el mismo de los correspondientes a los dispositivos de entrada/salida convencionales.
En cuanto a los servicios del reloj, se van a especificar de acuerdo a las tres categorías antes planteadas:
fecha y hora, temporizaciones y contabilidad. Con respecto a los servicios destinados a dispositivos
convencionales, se presentarán de forma genérica haciendo especial hincapié en los relacionados con el
terminal.

Servicio de fecha y hora

El servicio para obtener la fecha y hora es time, cuyo prototipo es el siguiente:

time_t time (time_t *t)

Esta función devuelve el número de segundos transcurridos desde el 1 de enero de 1970 en UTC. Si el
argumento no es nulo, también lo almacena en el espacio apuntado por el mismo.
Algunos sistemas UNIX proporcionan también el servicio gettimeofday que proporciona una precisión de
microsegundos.

La biblioteca estándar de C contiene funciones que transforman el valor devuelto por time a un formato
más manejable (año, mes, día, horas, minutos y segundos) tanto en UTC, la función gmtime, como en
horario local, la función localtime.
Para cambiar la hora y fecha se proporciona el servicio stime, cuyo prototipo es:
mt stime (timet *t)
Esta función fija la hora del sistema de acuerdo al parámetro recibido, que se interpreta como el número de
segundos desde el 1 de enero de 1970 en UTC. Se trata de un servicio sólo disponible para el superusuario.
En algunos sistemas UNIX existe la función settimeofday que permite realizar la misma función pero con
una precisión de microsegundos.
Todas estas funciones requieren el archivo de cabecera time . h.

Servicios de temporización

El servicio alarm permite establecer un temporizador en POSIX. El plazo debe especificarse en segundos.
Cuando se cumple dicho plazo, se le envía al proceso la señal SIGALRM. Sólo se permite un temporizador
activo por cada proceso. Debido a ello, cuando se establece un temporizador, se desactiva automáticamente
el anterior. El prototipo de esta función es el siguiente:

unsigned mt alarm (unsigned mt segundos);

El argumento especifica la duración del plazo en segundos. La función devuelve el número
de segundos que le quedaban pendientes a la alarma anterior, si había alguna pendiente. Una alarma con un
valor de cero desactiva un temporizador activo.
En POSIX existen otro tipo de temporizadores que permiten establecer plazos con una mayor resolución y con modos de operación más avanzados. Este tipo de temporizadores se activa con la función setitimer.

Servicios de contabilidad

POSIX define diversas funciones que se pueden englobar en esta categoría. Esta sección va a presentar una
de las más usadas. El servicio times que devuelve información sobre el tiempo de ejecución de un proceso y
de sus procesos hijos. El prototipo de la función es el siguiente:

clockt times (struct tms *info)

Servicios de entrada/salida sobre dispositivos

Corno ocurre en la mayoría de los sistemas operativos, se utilizan los mismos servicios que para acceder a
los archivos. En el caso de POSIX, por tanto, se trata de los servicios open, read, write y close.

Es necesario, sin embargo, un servicio que permita configurar las opciones específicas de cada dispositivo o
realizar operaciones que no se pueden expresar como un read o un write (corno, por ejemplo, rebobinar una
cinta).

La función tcgetattr obtiene los atributos del terminal asociado al descriptor especificado. La función
tcsetattr modifica los atributos del terminal que corresponde al descriptor pasado como parámetro. Su
segundo argumento establece cuándo se producirá el cambio: inmediatamente o después de que la salida
pendiente se haya transmitido.

La estructura termios contiene los atributos del terminal que incluye aspectos tales como el tipo de
procesado que se realiza sobre la entrada y sobre la salida, los parámetros de transmisión en el caso de un
terminal serie o la definición de qué caracteres tienen un significado especial. Dada la gran cantidad de
atributos existentes (más de 50), en esta exposición no se entrará en detalles sobre cada uno de ellos,
mostrándose simplemente un ejemplo de cómo se usan estas funciones.

Servicios de entrada/salida en Win32Se van a presentar clasificados en las mismas categorías que se han usado para exponer los servicios POSIX.

Servicios de fecha y hora

El servicio para obtener la fecha y hora es GetSystemTime, cuyo prototipo es el siguiente:
BOOL GetSystemTime (LPSYSTEMTIME tiempo)

Esta función devuelve en el espacio asociado a su argumento la fecha y hora actual en una estructura
organizada en campos que contienen el año, mes, día, hora, minutos, segundos y milisegundos. Los datos
devueltos corresponden con el horario estándar UTC. La función GetLocal Time permite obtener
información según el horario local.
La función que permite modificar la fecha y hora en el sistema es SetSystemTime, cuyo prototipo es:
BOOL SetSystemTime (LPSYSTEMTIME tiempo);
Esta función establece la hora del sistema de acuerdo al parámetro recibido que tiene la misma
estructura que el usado en la función anterior (desde el año hasta los milisegundos actuales).


Servicios de temporización

La función setTimer permite establecer un temporizador con una resolución de milisegundos. Un proceso
puede tener múltiples ternporizadores activos simultáneamente. El prototipo es:
UINT SetTimer (HWND ventana, UINT evento, UINT plazo,
TIMERPROC funcion);

Esta función devuelve un identificador del temporizador y recibe como parámetros un identificador de la
ventana asociada con el temporizador (si tiene un valor nulo no se le asocia a ninguna), un identificador del
evento (este parámetro se ignora en el caso de que el temporizador no esté asociado a ninguna ventana), un
plazo en milisegundos y la función que se invocará cuando se cumpla el plazo.

Servicios de contabilidad

En Win32 existen diversas funciones que se pueden encuadrar en esta categoría. Como en el caso de
POSIX, se muestra como ejemplo el servicio que permite obtener información sobre el tiempo de ejecución
de un proceso. Esta función es GetProcessTimes y su prototipo es el siguiente:
BOOL GetProcessTimes (HANDLE proceso, LPFILETIME t_creacion,
LPFILETIME t_fin, LPFILETIME tsistema,
LPFILETIME tusuario);

Esta función obtiene para el proceso especificado su tiempo de creación y finalización, así como cuánto
tiempo de procesador ha gastado en modo sistema y cuánto en modo usuario. Todos estos tiempos están
expresados como centenas de nanosegundos transcurridas desde el 1 de enero de 1601 almacenándose en
un espacio de 64 bits. La función FileTimeToSystemTime permite transformar este tipo de valores en el
formato ya comentado de año, mes, día, hora, minutos, segundos y milisegundos.

Servicios de entrada/salida

Al igual que en POSIX, para acceder a los dispositivos se usan los mismos servicios que se utilizan para los
archivos. En este caso, createFile, CloseHandie, ReadFile y WriteFile.
Sin embargo, como se ha analizado previamente, estos servicios no son suficientes para cubrir
todos los aspectos específicos de cada tipo de dispositivo. Centrándose en el caso del terminal, Win32
ofrece un servicio que permite configurar el modo de funcionamiento del mismo.

LA RED

El dispositivo de red se ha convertido en un elemento fundamental de cualquier sistema informático. Por
ello, el sistema operativo ha evolucionado para proporcionar un tratamiento más exhaustivo y sofisticado
de este dispositivo.

Se trata de un dispositivo que presenta unas características específicas que generalmente implican un
tratamiento diferente al de otros dispositivos. Así, muchos sistemas operativos no proporcionan una
interfaz basada en archivos para el acceso a la red, aunque sí lo hacen para el resto de dispositivos. En
Linux, por ejemplo, no hay archivos en /dev que representen a los dispositivos de red. Los manejadores de
estos dispositivos de red se activan automáticamente cuando en el arranque del sistema se detecta el
hardware de red correspondiente, pero no proporcionan acceso directo a los programas de usuario.

Típicamente, el software de gestión de red del sistema operativo se organiza en tres niveles:
• Nivel de interfaz a las aplicaciones.
• Nivel de protocolos. Este nivel, a su vez, puede estar organizado en niveles que se corresponden
con la pila de protocolos.
• Nivel de dispositivo red.

Con respecto al nivel superior, una de las interfaces más usadas es la que corresponde con los sockets del
UNIX BSD, que incluso se utiliza en sistemas Windows ( Winsock). Esta interfaz tiene servicios específicos que sólo se usan para acceder a la red (como, por ejemplo, connect, bind, accept y sendto), aunque usa descriptores de archivo para representar a las conexiones y permite utilizar servicios convencionales de archivo (como read, write y close). Se puede considerar que se trata de un nivel de sesión de OSI.

El nivel intermedio consta de una o más capas que implementan los niveles de transporte y de red de OSI (o
los niveles TCP e IP en el caso de Internet). Este nivel se encarga también de funciones de encaminamiento.
En el nivel inferior están los manejadores de los dispositivos de red que se corresponden con el nivel de
enlace de OSI. En este nivel puede haber manejadores para distintos tipos de hardware de red (Ethernet,
SLIP, etc.).

Todos estos niveles trabajan de manera independiente entre sí, lo que facilita la coexistencia de distintos
protocolos y dispositivos de red. Para lograr esta independencia se definen interfaces estándar entre los
distintos niveles.
La información viajará del nivel superior a los inferiores como resultado de una llamada de una aplicación
solicitando transferir un mensaje. El flujo inverso de información se activa con la ocurrencia de una
interrupción del dispositivo de red que indica la llegada de un mensaje.

Según la información va pasando por los distintos niveles se va añadiendo y eliminando información de
control. Un aspecto fundamental para conseguir una implementación eficiente del software de gestión de
red es intentar reducir lo máximo posible el número de veces que se copia la información del mensaje.
La Figura muestra cómo están organizados los distintos niveles de software del sistema operativo que
gestiona la red.

EL TERMINAL

Se trata de un dispositivo que permite al usuario comunicarse con el sistema y que está presente en todos
los sistemas de propósito general actuales. Está formado típicamente por un teclado que permite introducir
información y una pantalla que posibilita su visualización.

Hay una gran variedad de dispositivos de este tipo, los terminales serie y los proyectados en memoria.

Modo de operación del terminal

El modo de operación básico de todos los terminales es bastante similar a pesar de su gran diversidad. La
principal diferencia está en qué operaciones se realizan por hardware y cuáles por software. En todos ellos
existe una relativa independencia entre la entrada y salida.

Entrada

Cuando el usuario pulsa una tecla en un terminal, se genera un código de tecla que la identifica. Este código
de tecla debe convertirse en el carácter ASCII correspondiente teniendo en cuenta el estado de las teclas
modificadoras (típicamente, Control, Shift y Alt). Así, por ejemplo, si está pulsada la tecla Shift al teclear la
letra “a”, el carácter resultante será “A”.

Salida

Una pantalla de vídeo está formada por una matriz de pixels. Asociada a la misma existe una memoria de
vídeo que contiene información que se visualiza en la pantalla. El controlador de vídeo es el encargado de
leer la información almacenada en dicha memoria y usarla para refrescar el contenido de la pantalla con la
frecuencia correspondiente. Para escribir algo en una determinada posición de la pantalla sólo es necesario
modificar las direcciones de memoria de vídeo correspondientes a esa posición.
Cuando un programa solicita escribir un determinado carácter ASCII en la pantalla, se debe obtener el
patrón rectangular que representa la forma de dicho carácter, lo que dependerá del tipo de fuente de texto
utilizado. El controlador visualizará dicho patrón en la posición correspondiente de la pantalla.

Además de escribir caracteres, un programa necesita realizar otro tipo de operaciones, tales
como borrar la pantalla o mover el cursor a una nueva posición. Este tipo de operaciones están
generalmente asociadas a ciertas secuencias de caracteres.

Cuando un programa escribe una de estas secuencias, no se visualiza información en la pantalla sino que se
lleva a cabo la operación de control asociada a dicha secuencia. Típicamente, por razones históricas, estas
secuencias suelen empezar por el carácter Escape.

Hardware del terminal

Terminales proyectados en memoria



El teclado genera una interrupción cuando se aprieta una tecla (en algunos sistemas también se genera
cuando se suelta). Cuando se produce la interrupción, el código de la tecla pulsada queda almacenado en un
registro de entrada/salida del controlador del teclado. Observe que tanto la conversión desde el código de
tecla hasta el carácter ASCII como el tratamiento de las teclas modificadoras los debe realizar el software.
En este tipo de terminales, la memoria de vídeo está directamente accesible al procesador. Por tanto, la
presentación de información en este tipo de terminales implica solamente la escritura del dato que se
pretende visualizar en las posiciones correspondientes de la memoria de vídeo, no requiriéndose el uso de
interrupciones para llevar a cabo la operación.

Con respecto a la información que se escribe en la memoria de vídeo, va a depender de si el modo de operación del terminal es alfanumérico o gráfico.
En el modo alfanumérico se considera la pantalla como una matriz de caracteres, por lo que la memoria de vídeo contiene el código ASCII de cada carácter presente en la pantalla. Durante una operación de refresco de la pantalla, el controlador va leyendo de la memoria cada carácter y el mismo se encarga de obtener el patrón de bits correspondiente al carácter en curso y lo visualiza en la pantalla.

Por lo que se refiere al modo gráfico, en este caso la pantalla se considera una matriz de pixeis y la
memoria de vídeo contiene información de cada uno de ellos. Cuando un programa solicita escribir un
carácter, debe ser el software el encargado de obtener el patrón de bits que define dicho carácter.
El trabajo con un terminal de este tipo no se limita a escribir en vídeo. El controlador de vídeo contiene un
conjunto de registros de entrada/salida que permiten realizar operaciones como mover la posición del cursor
o desplazar el contenido de la pantalla una o varias líneas.
Un último aspecto que conviene resaltar es que en este tipo de terminales el tratamiento de las secuencias
de escape debe ser realizado por el software.

Terminales serie

En este tipo de terminales, como se puede apreciar en la Figura, el terminal se presenta ante el resto
del sistema como un único dispositivo conectado, típicamente a través de una línea serie RS-232. al
controlador correspondiente denominado UART (Universal Asynchronous Receiver Transmitter,
Transmisor-Receptor Universal Asíncrono). Además de la pantalla y el teclado, el terminal tiene algún tipo
de procesador interno que realiza parte de la gestión del terminal y que permite también al usuario
configurar algunas de las características del mismo. Para poder dialogar con el terminal, se deben
programar diversos aspectos de la UART tales como la velocidad de transmisión o el número de bits de
parada que se usarán en la transmisión.

Al igual que ocurre con los terminales proyectados en memoria, la entrada se gestiona mediante interrupciones. Cuando se pulsa una tecla, el terminal envía a través de la línea serie el carácter pulsado. La
UART genera una interrupción al recibirlo. A diferencia de los terminales proyectados en memoria, el
carácter que recoge de la UART ya es el código ASCII de la tecla pulsada puesto que el procesador del
terminal se encarga de pasar del código de la tecla al código ASCII y de comprobar el estado de las teclas
modificadoras.

Para la visualización de información en este tipo de terminales se debe cargar el código ASCII del carácter
deseado en un registro de la UART y pedir a ésta que lo transmita. Una vez transmitido, lo que puede llevar un tiempo considerable debido a las limitaciones de la transmisión serie, la UART produce una interrupción para indicar este hecho. Por lo que se refiere al terminal, cuando recibe el carácter ASCII se encarga de obtener su patrón y visualizarlo en la pantalla, manejando asimismo las secuencias de escape.

EL RELOJ

El reloj es un elemento imprescindible en cualquier sistema informático. Es necesario aclarar desde el
principio que se trata de un término que presenta varias acepciones en este entorno:

• El reloj del procesador, que marca el ritmo con el que se ejecutan las instrucciones.
• El reloj del sistema, que mantiene la fecha y la hora en el mismo.
• El reloj temporizador, que hace que el sistema operativo se active periódicamente para realizar las
labores correspondientes.

La primera acepción queda fuera de esta presentación ya que no involucra al sistema operativo,
consistiendo generalmente en una señal generada por un cristal de cuarzo que alimenta directamente el
procesador. Este apartado se centra en los dos últimos sentidos del término ya que en ellos sí que interviene
el sistema operativo.

El hardware del reloj

Para medir el tiempo sólo se requiere un componente que genere una señal periódica que sirva como base
de tiempo. Normalmente se dispone de un circuito temporizador que, a partir de las oscilaciones producidas por un cristal de cuarzo, genera periódicamente interrupciones (a cada una de estas interrupciones del reloj se las suele denominar en inglés tick). Este elemento está conectado generalmente a una línea de interrupción de alta prioridad del procesador debido a la importancia de los eventos que produce.

La mayoría de estos temporizadores permiten programar su frecuencia de interrupción. Típicamente
contienen un registro interno que actúa como un contador que se decrementa por cada oscilación del cristal
generando una interrupción cuando llega a cero. El valor que se carga en este contador determina la
frecuencia de interrupción del temporizador, que se comporta, por tanto, como un divisor de frecuencia.
Además de ser programable la frecuencia de interrupción, estos dispositivos frecuentemente presentan
varios modos de operación seleccionables. Suelen poseer un modo de «un solo disparo» en el que cuando el
contador llega a cero y se genera la interrupción, el temporizador se desactiva hasta que se le reprograme
cargando un nuevo valor en el contador. Otro típico modo de operación es el de «onda cuadrada» en el que
al llegar a cero el contador y generar la interrupción el propio temporizador vuelve a recargar el valor
original en el contador sin ninguna intervención externa.

Hay que resaltar que generalmente un circuito de este tipo incluye varios temporizadores independientes, lo
que permite, en principio, que el sistema operativo lo use para diferentes labores. Sin embargo, en muchos
casos no todos ellos son utilizables para esta misión ya que no están conectados a líneas de interrupción del
procesador.
Un ejemplo típico de este componente es el circuito temporizador 8253 que forma parte de un PC estándar.
Tiene tres temporizadores pero sólo uno de ellos está conectado a una línea de interrupción (en concreto, a
la línea IRQ número O). Los otros están destinados a otros usos. Por ejemplo, uno de ellos está conectado al altavoz del equipo. La frecuencia de entrada del circuito es de 1,193 MHz. Dado que utiliza un contador
interno de 16 bits, el temporizador se puede programar en el rango de frecuencias desde 18,5 Hz (con el
contador igual a 65536) hasta 1,193 MHz (con el contador igual a 1). Cada temporizador puede
programarse de forma independiente presentando diversos modos de operación, entre ellos, el de «un solo
disparo» y el de «onda cuadrada».

Otro elemento hardware presente en prácticamente la totalidad de los equipos actuales es un reloj
alimentado por una batería (denominado en ocasiones reloj CMOS) que mantiene la fecha y la hora cuando
la máquina está apagada.

El software del reloj

Dado que la labor fundamental del hardware del reloj es la generación periódica de interrupciones, el
trabajo principal de la parte del sistema operativo que se encarga del reloj es el manejo de estas
interrupciones. Puesto que, como se analizará a continuación, las operaciones asociadas al tratamiento de
una interrupción de reloj pueden implicar un trabajo considerable, es preciso establecer un compromiso a la
hora de fijar la frecuencia de interrupción del reloj de manera que se consiga una precisión aceptable en la
medición del tiempo, pero manteniendo la sobrecarga debida al tratamiento de las interrupciones en unos
términos razonables. Un valor típico de frecuencia de interrupción, usado en muchos sistemas UNIX, es de
100 Hz (o sea, una interrupción cada 10 ms).
Hay que resaltar que, dado que las interrupciones del reloj son de alta prioridad, mientras se procesan no se
aceptan interrupciones de otros dispositivos menos prioritarios. Se debe, por tanto. minimizar la duración
de la rutina de tratamiento para asegurar que no se pierden interrupciones de menor prioridad debido a la
ocurrencia de una segunda interrupción de un dispositivo antes de que se hubiera tratado la primera. Para
evitar esta posibilidad, muchos sistemas operativos dividen el trabajo asociado con una interrupción de reloj
en dos partes:

• Operaciones más urgentes que se ejecutan en el ámbito de la rutina de interrupción.
• Operaciones menos urgentes que lleva a cabo una rutina que ejecuta con una prioridad más baja
que cualquier dispositivo del sistema. Esta función es activada por la propia rutina de interrupción
de reloj mediante un mecanismo generalmente denominado interrupción software (en el caso de
Linux se denomina «mitad inferior»).

Aunque la labor principal del sistema operativo con respecto al manejo del reloj es el tratamiento de sus
interrupciones, hay que hacer notar que también debe realizar su iniciación y llevar a cabo las llamadas al
sistema relacionadas con el mismo.
Con independencia de cual sea el sistema operativo específico, se pueden identificar las siguientes
operaciones como las funciones principales del software de manejo del reloj:
• Mantenimiento de la fecha y de la hora.
• Gestión de temporizadores.
• Contabilidad y estadísticas.
• Soporte para la planificación de procesos.

Mantenimiento de la fecha y de la hora

En el arranque del equipo, el sistema operativo debe programar el circuito temporizador del sistema
cargándole en su contador interno el valor correspondiente a la frecuencia deseada y estableciendo un modo
de operación de «onda cuadrada», si es que el temporizador dispone del mismo. Asimismo, debe leer el
reloj mantenido por una batería para obtener la fecha y hora actual.
A partir de ese momento, el sistema operativo se encargará de actualizar la hora según se vayan
produciendo las interrupciones.
La principal cuestión referente a este tema es cómo se almacena internamente la información de la fecha y
la hora. En la mayoría de los sistemas la fecha se representa como el número de unidades de tiempo
transcurridas desde una determina fecha en el pasado. Por ejemplo, los sistemas UNIX toman como fecha
base el 1 de enero de 1970. Algunos de ellos almacenan el número de segundos transcurridos desde esta
fecha, mientras que otros guardan el número de microsegundos que han pasado desde entonces. Por lo que
se refiere a Windows, la fecha se almacena Como el número de centenas de nanosegundos (l0- segundos)
transcurridos desde la fecha de referencia del 1 de enero de 1601.
Sea cual sea la información almacenada para mantener la fecha y la hora, es muy importante que se le dedique un espacio de almacenamiento suficiente para que se puedan representar fechas en un futuro a
medio o incluso a largo plazo. De esta forma se asegura que la vida del sistema operativo no quede limitada
por este aspecto. Así, por ejemplo, un sistema UNIX que use una variable de 32 bits para guardar el número de segundos desde la fecha de referencia (1- 1-1970) permitiría representar fechas hasta principios del siglo XXII.

Otro aspecto importante es cómo tratar las peculiaridades existentes en el horario de cada país. Esto no sólo
implica las diferencias que hay dependiendo del huso horario al que pertenezca el país, sino también la
existencia en algunos países de políticas de cambio de horario con el objetivo de ahorrar energía. En el caso
del sistema UNIX, el sistema operativo almacena la hora en el sistema de tiempo estándar UTC (Universal
Ceordinated Time), con independencia de las peculiaridades del país donde reside la máquina. La
conversión al horario local no la realiza el sistema operativo sino las bibliotecas del sistema.
Por último, es interesante resaltar que algunos sistemas operativos, además de un servicio para cambiar la
hora en el sistema de forma inmediata, ofrecen un servicio que permite hacer este ajuste de forma progresiva, para así no perturbar bruscamente el estado del sistema. Observe que un cambio inmediato de la
hora que implique un retraso de la misma puede causar situaciones problemáticas en el sistema (evidentemente, el tiempo real nunca va hacia atrás).

Gestión de temporizadores

En numerosas ocasiones un programa necesita esperar un cierto plazo de tiempo antes de realizar una
determinada acción. El sistema operativo ofrece servicios que permiten a los programas establecer
temporizaciones y se encarga de notificarles cuando se cumple el plazo especificado (en caso de UNIX
mediante una señal). Pero no sólo los programas de usuario necesitan este mecanismo, el propio sistema
operativo también lo requiere. El módulo de comunicaciones del sistema operativo, por ejemplo, requiere
establecer plazos de tiempo para poder detectar si un mensaje se pierde. Otro ejemplo es el manejador del
disquete que, una vez arrancado el motor del mismo, requiere esperar un determinado tiempo para que la
velocidad de rotación se estabilice antes de poder acceder al dispositivo.

Dado que en la mayoría de los equipos existe un único temporizador (o un número muy reducido de ellos),
es necesario que el sistema operativo lo gestione de manera que sobre él puedan crearse los múltiples
temporizadores que puedan requerirse en el sistema en un determinado momento.
El sistema operativo maneja generalmente de manera integrada tanto los temporizadores de los procesos de
usuario como los internos. Para ello mantiene una lista de temporizadores activos. En cada elemento de la
lista se almacena típicamente el número de unidades de tiempo (para facilitar el trabajo, generalmente se
almacena el número de interrupciones de reloj requeridas) que falta para que se cumpla el plazo y la
función que se invocará cuando éste finalice. Así, en el ejemplo del disquete se corresponderá con una
función del manejador de dicho dispositivo. En el caso de una temporización de un programa de usuario, la
función corresponderá con una rutina del sistema operativo encargada de mandar la notificación al proceso
(en UNIX, la señal).

Existen diversas alternativas a la hora de gestionar la lista de temporizadores. Una organización típica
consiste en ordenar la lista de forma creciente según el tiempo que queda por cumplirse el plazo de cada
temporizador. Además, para reducir la gestión asociada a cada interrupción, el plazo de cada temporizador
se guarda de forma relativa a los anteriores en la lista. Así se almacenan las unidades que quedarán
pendientes cuando se hayan cumplido todas las temporizaciones correspondientes a elementos anteriores
de la lista. Con este esquema se complica la inserción, puesto que es necesario buscar la posición
correspondiente en la lista y reajustar el plazo del elemento situado a continuación de la posición de inserción. Sin embargo, se agiliza el tratamiento de la interrupción  ya que sólo hay que modificar el elemento de cabeza, en lugar de tener que actualizar todos los temporizadores.

En último lugar hay que resaltar que generalmente la gestión de temporizadores es una de las operaciones
que no se ejecutan directamente dentro de la rutina de interrupción sino, como se comentó previamente, en
una rutina de menor prioridad. Esto se debe a que esta operación puede conllevar un tiempo considerable
por la posible ejecución de las rutinas asociadas a todos aquellos temporizadores que se han cumplido en la
interrupción de reloj en curso.

Contabilidad y estadísticas

Puesto que la rutina de interrupción se ejecuta periódicamente, desde ella se puede realizar un muestreo de
diversos aspectos del estado del sistema llevando a cabo funciones de contabilidad y estadística. Es
necesario resaltar que, dado que se trata de un muestreo del comportamiento de una determinada variable y
no de un seguimiento exhaustivo de la misma, los resultados no son exactos, aunque si la frecuencia de
interrupción es suficientemente alta, pueden considerarse aceptables.

Dos de las funciones de este tipo presentes en la mayoría de los sistemas operativos son las siguientes:
• Contabilidad del uso del procesador por parte de cada proceso.
• Obtención de perfiles de ejecución.

Por lo que se refiere a la primera función, en cada interrupción se detecta qué proceso está ejecutando y a
éste se le carga el uso del procesador en ese intervalo. Generalmente, el sistema operativo distingue a la
hora de realizar esta contabilidad si el proceso estaba ejecutando en modo usuario o en modo sistema.

Algunos sistemas operativos utilizan también esta información para implementar temporizadores virtuales,
en los que el reloj sólo «corre» cuando está ejecutando el proceso en cuestión, o para poder establecer
límites en el uso del procesador.

Con respecto a los perfiles, se trata de obtener información sobre la ejecución de un programa que permita
determinar cuánto tiempo tarda en ejecutarse cada parte del mismo. Esta información permite que el
programador detecte los posibles cuellos de botella del programa para poder así optimizar su ejecución.
Cuando un proceso tiene activada esta opción, el sistema operativo toma una muestra del valor del contador
de programa del proceso cada vez que una interrupción encuentra que ese proceso estaba ejecutando.

La acumulación de esta información durante toda la ejecución del proceso permite que el sistema operativo
obtenga una especie de histograma de las direcciones de las instrucciones que ejecuta el programa.

Soporte a la planificación de procesos
La mayoría de los algoritmos de planificación de procesos tienen en cuenta de una forma u otra el tiempo y,
por tanto, implican la ejecución de ciertas acciones de planificación dentro de la rutina de interrupción.
En el caso de un algoritmo round-robin, en cada interrupción de reloj se le descuenta el tiempo
correspondiente a la rodaja asignada al proceso. Cuando se produce la interrupción de reloj que consume la
rodaja, se realiza la replanificación.
Otros algoritmos requieren que cada cierto tiempo se recalcule la prioridad de los procesos teniendo en
cuenta el uso del procesador en el último intervalo. Nuevamente, estas acciones estarán
asociadas con la interrupción de reloj.

ALMACENAMIENTO TERCIARIO

Los sistemas de almacenamiento secundario están bien para acceso rápido a datos y programas, sin
embargo tienen tres problemas serios:
1. Poca capacidad.
2. Alto coste.
3. No se pueden extraer de la computadora.

En algunos sistemas de almacenamiento es necesario disponer de dispositivos extraíbles y de alta capacidad
para poder hacer copias de respaldo de datos o para archivar datos que se usan poco frecuentemente. Estas dos necesidades justifican la existencia de almacenamiento terciario, que se puede definir como un sistema de almacenamiento de alta capacidad, bajo coste y con dispositivos extraíbles en el que se almacenan los datos que no se necesitan de forma inmediata en el sistema.

ALMACENAMIENTO SECUNDARIO

El sistema de almacenamiento secundario se usa para guardar los programas y datos en dispositivos
rápidos, de forma que sean fácilmente accesibles a las aplicaciones a través del sistema de archivos.


La Figura  muestra el sistema de E/S en el sistema operativo LINUX y la parte del mismo correspondiente a la gestión del sistema de almacenamiento secundario. Como se puede ver, hay dos elementos principales involucrados en este sistema.
• Discos. El almacenamiento secundario se lleva a cabo casi exclusivamente sobre discos, por lo que es interesante conocer su estructura y cómo se gestionan.
• Manejadores de disco. Controlan todas las operaciones que se hacen sobre los discos, entre las que son especialmente Importantes las cuestiones de planificación de peticiones a disco.
En esta sección se tratan los principales aspectos relativos a estos dos componentes, así como algunos otros relativos a tolerancia a fallos y fiabilidad.

Discos

Los discos son los dispositivos básicos para llevar a cabo almacenamiento masivo y no volátil de datos.
Además se usan como plataforma para el sistema de intercambio que usa el gestor de memoria virtual. Son
dispositivos electromecánicos (HARD DISK) u optomecánicos (CD-ROM y DVD), que se acceden a nivel
de bloque lógico por el sistema de archivos y que, actualmente, se agrupan en dos tipos básicos, atendiendo
a la interfaz de su controlador:
• Dispositivos SCSI (Small Computer System Inteiface), cuyos controladores ofrecen una interfaz común independientemente de que se trate de un disco, una cinta, un CD-ROM, etc. Un controlador SCSI puede manejar hasta ocho discos y puede tener una memoria interna de varios MB.
• Dispositivos IDE (Integrated Drive Electronics), que suelen usarse para conectar los discos en todas las computadoras personales. Actualmente estos controladores se han extendido al sistema EIDE, una mejora de IDE que tiene mayor velocidad de transferencia. Puede manejar hasta cuatro discos IDE. Es barato y muy efectivo.

Y a tres tipos básicos atendiendo a su tecnología de fabricación:
• Discos duros (Winchester). Dispositivos de gran capacidad compuestos por varias superficies magnetizadas y cuyas cabezas lectoras funcionan por efecto electromagnético. Actualmente su capacidad máxima está en los 30 GB, pero se anuncian discos de 100 GB y más.
• Discos ópticos. Dispositivos de gran capacidad compuestos por una sola superficie y cuyas cabezas lectoras funcionan por láser. Actualmente su capacidad máxima está en los 700 MB. Hasta hace muy poco, la superficie se agujereaba físicamente y no se podían regrabar. Sin embargo, actualmente existen discos con superficie magnética regrabables.
• Discos extraíbles. Dispositivos de poca capacidad similares a un disco duro, pero cuyas cabezas
lectoras se comportan de forma distinta. En este tipo se engloban los disquetes (floppies), discos
ZIP y JAZZ.

Dispositivos RAID

Una técnica más actual para proporcionar fiabilidad y tolerancia a fallos consiste en usar dispositi vos
RAID (Redundant Array of Independent Disks) a nivel hardware [ 19951 o software EChen, 1995]. Estos
dispositivos usan un conjunto de discos para almacenar la información y otro conjunto para almacenar
información de paridad del conjunto anterior. En el ámbito físico se ven como un único
dispositivo, ya que existe un único controlador para todos los discos. Este controlador se encarga de
reconfigurar y distribuir los datos como es necesario de forma transparente al sistema de FIS.
Se han descrito hasta siete niveles de RAID, pero solamente los cinco primeros están realmente operativos.

Estos niveles son los siguientes:

• RAID 1. Son discos espejo en los cuales se tiene la información duplicada. Tiene los problemas y las
ventajas del almacenamiento estable.
• RAID 2. Distribuye los datos por los discos, repartiéndolos de acuerdo con una unidad de distribución
definida por el sistema o la aplicación. El grupo de discos se usa como un discológico, en el que se
almacenan bloques lógicos distribuidos según la unidad de reparto.
• RAID 3. Reparte los datos a nivel de bit por todos los discos. Se puede añadir bits con códigos correctores
de error. Este dispositivo exige que las cabezas de todos los discos estén
sincronizadas, es decir, que un único controlador controle sus movimientos.
• RAID 4. Reparto de bloques y cálculo de paridad para cada franja de bloques, que se almacena en un
disco fijo. En un grupo de cinco discos, por ejemplo, los cuatro primeros serían de datos y el quinto de
paridad. Este arreglo tiene el problema de que el disco de paridad se convierte en un cuello de botella y un
punto de fallo único.
• RAID 5. Reparto de bloques y paridad por todos los discos de forma cíclica. Tiene la ventaja de la
tolerancia a fallos sin los inconvenientes del RAID 4. Actualmente existen múltiples dispositivos comerciales de este estilo y son muy populares en fiabilidad.

La Figura muestra un dispositivo de tipo RAID 5, donde toda la paridad se reparte por todos los discos
de forma cíclica. La paridad se calcula por hardware en el controlador haciendo el X-OR de los bloques de
datos de cada franja. Esto conlieva problemas si las escrituras no llenan todos los discos de datos (escrituras
pequeñas), ya que hay que leer los datos restantes para calcular la paridad. Sin embargo, los RAID
proporcionan un gran ancho de banda para lecturas y escrituras grandes.

Sistemas operativos. Una visión aplicada - Jesús Carretero

INTERFAZ DE APLICACIONES

Las aplicaciones tienen acceso al sistema de E/S a través de las llamadas al sistema operativo relacionadas
con la gestión de archivos y con la E/S, como íoctl por ejemplo. En muchos casos, las aplicaciones no
acceden directamente a las llamadas del sistema, sino a utilidades que llaman al sistema en representación
del usuario. Las principales utilidades de este estilo son:
• Las bibliotecas de los lenguajes, como la libc.so de C, que traducen la petición del usuario a llamadas del sistema, convirtiendo los parámetros allí donde es necesario. Ejemplos de utilidades de biblioteca en C son fread, fwríte o printf. Las bibliotecas de enlace dinámico (DLL) de Windows. Por ejemplo, Kernel32 .dll incluye llamadas para la gestión de archivos y otros componentes de E/S.
• Los demonios del sistema, como los de red o los spooler de las impresoras. Son programas privilegiados que pueden acceder a recursos que las aplicaciones normales tienen vetados. Así, por ejemplo, cuando una aplicación quiere acceder al puerto de telnet, llama al demonio de red (inetd) y le pide este servicio. De igual forma, cuando se imprime un archivo, no se envía directamente a la impresora, sino que se envía a un proceso spooler que lo copia a unos determinados directorios y, posteriormente, lo imprime.
Esta forma de relación a través de representantes existe principalmente por razones de seguridad y de
control de acceso. Es fácil dejar que un proceso spooler, generalmente desarrollado por el fabricante del
sistema operativo y en el que se confía, acceda a la impresora de forma controlada, lo que evita problemas
de concurrencia, filtrando los accesos del resto de los usuarios.
La interfaz de E/S de las aplicaciones es la que define el modelo de E/S que ven los usuarios, por lo
que, cuando se diseña un sistema operativo, hay que tomar varias decisiones relativas a la funcionalidad que
se va a ofrecer al mundo exterior en las siguientes cuestiones:

• Nombres independientes de dispositivo.
• E/S bloqueante y no bloqueante.
• Control de acceso a dispositivos compartidos y dedicados.
• Indicaciones de error.
• Uso de estándares.

La elección de unas u otras características determina la visión del sistema de E/S del usuario.

A continuación, se estudian brevemente cada una de ellas.

Nombres independientes de dispositivo

Usar nombres independientes de dispositivo permite construir un árbol completo de nombres lógicos, sin
que el usuario vea en ningún momento los dispositivos a los que están asociados. La utilidad mount de
UNIX es un buen ejemplo de diseño. Si se monta el dispositivo /dev/hda3 sobre el directorio lógico /users,
a partir de ese instante todos los archivos del dispositivo se pueden acceder a través de /users, sin que el
nombre del dispositivo se vea en ningún momento. Es decir, que el archivo /dev/hda.3/pepe pasa a ser
/users/pepe después de la operación de montado.
Usar un árbol de nombres único complica la traducción de nombres, por lo que algunos sistemas
operativos, como Windows NT, no la incluyen. En Windows, cuando se accede a un dis positivo con un
nombre completo, siempre hay que escribir el nombre del dispositivo al que se accede (C:, D:, etc.). En las
últimas versiones se enmascaran los dispositivos con unidades de red, pero siempre hay que saber a cuál se
quiere acceder. Por ejemplo, Condor\users\profesores (Z:) identifica a una unidad de red que está en la
máquina Condor y que está montada en la computadora local sobre el dispositivo lógico z:. No hay en este
sistema un árbol de nombres único tan claramente identificado como en UNIX o LINUX.

E/S bloqueante y no bloqueante

La mayoría de los dispositivos de E/S son no bloqueantes, también llamados asíncronos, es decir, reciben la
operación, la programan, contestan e interrumpen al cabo de un cierto tiempo. Sólo los dispositivos muy
rápidos o algunos dedicados fuerzan la existencia de operaciones de E/S bloqueantes (también llamadas
síncronas). Sin embargo, la mayoría de las aplicaciones efectúan operaciones de E/S con lógica bloqueante,
lo que significa que emiten la operación y esperan hasta tener el resultado antes de continuar su ejecución.
En este tipo de operaciones, el sistema operativo recibe la operación y bloquea al proceso emisor hasta que
la operación de E/S ha terminado , momento en que desbloquea a la aplicación y le envía el estado del resultado de la opera ción. En este caso, la aplicación puede acceder a los datos inmediatamente, ya que los tiene disponi bles en la posición de memoria especificada, a no ser que hubiera un error de E/S.
Este modelo de programación es claro y sencillo, por lo que las principales llamadas al sistema de E/S.
como read o write en POSEX y ReadFile y WriteFile en Win32, bloquean al usuario y completan la
operación antes de devolver el control al usuario.


Las llamadas de E/S no bloqueantes se comportan de forma muy distinta, reflejando mejor Ja propia
naturaleza del comportamiento de los dispositivos de E/S. Estas llamadas permiten a la aplicación seguir su
ejecución, sin bloquearla, después de hacer una petición de E/S . El procesamiento de la
llamada de E/S consiste en recuperar los parámetros de la misma, asignar un identificador de operación de
E/S pendiente de ejecución y devolver a la aplicación este identificador. Las llamadas de POSIX aioread
aiowrite permiten realizar operaciones no bloqueantes. A continuación, el sistema operativo ejecuta la
operación de E/S en concurrencia con la aplicación, que sigue ejecutando su código. Es responsabilidad de la aplicación preguntar por el estado de la operación de E/S, usando una llamada al sistema especial para realizar esta consulta (alo walt), o cancelarla si ya no le interesa o tarda demasiado (aiocancel). En Windows se puede conseguir este mismo efecto indicando, cuando se crea el archivo, que se desea E/S no bloqueante (FILE_FLAG y usando las llamadas ReadFileEx y WriteFileEx.

Este modelo de programación es más complejo, pero se ajusta muy bien al modelo de algunos sistemas
que emiten peticiones y reciben la respuesta después de un cierto tiempo. Un programa que esté leyendo
datos de varios archivos, por ejemplo, puede usarlo para hacer lectura adelantada de datos y tener los datos
de un archivo listos en memoria en el momento de procesarlos. Un programa que escuche por varios
canales de comunicaciones podría usar también este modelo.

Es interesante resaltar que, independientemente del formato elegido por el usuario, el sistemaoperativo
procesa siempre las llamadas de E/S de forma no bloqueante, o asíncrona, para permitir la implementación
de sistemas de tiempo compartido.

Control de acceso a dispositivos

Una de las funciones más importantes de la interfaz de usuario es dar indicaciones de control de acceso a
los dispositivos e indicar cuáles son compartidos y cuáles dedicados. En general, las llamadas al sistema no
hacen este tipo de distinciones, que, sin embargo, son necesarias. Imagine qué ocurriría si dos archivos se
escribieran en la impresora sin ningún control. Ambos saldrían mezclados, siendo el resultado del trabajo
inútil.
Para tratar de resolver este problema se usan dos tipos de mecanismos:
• Mandatos externos (como el lpr para la impresora) o programas especiales (demonios) que se
encargan de imponer restricciones de acceso a los mismos cuando es necesario.
• Llamadas al sistema que permiten bloquear (lock) y desbloquear (unlock) el acceso a un dispositivo
o a parte de él. Usando estas llamadas, una aplicación se puede asegurar acceso exclusivo bloqueando el dispositivo antes de acceder y desbloqueándolo al terminar sus accesos. Para evitar problemas de bloqueos indefinidos, sólo se permiten bloqueos aconsejados (advisory), nunca obligatorios. Además, es habitual que el único usuario que puede bloquear un dispositivo de E/S como tal sea el administrador del sistema. Para el resto de usuarios, este privilegio se restringe a sus archivos.
La seguridad es un aspecto importante del control de accesos. No basta con que se resuelvan los conflictos de acceso. Hay que asegurar que el usuario que accede al sistema de E/S tiene de rechos de acceso suficientes para llevar a cabo las operaciones que solicita. En UNIX y LINUX, los aspectos de seguridad se gestionan en el gestor de archivos. En Windows NT existe un servidor de seguridad que controla los  ccesos a los objetos.

Indicaciones de error

Las operaciones del sistema operativo pueden fallar debido a cuestiones diversas. Es importante decidir
cómo se va a indicar al usuario esos fallos.

En UNIX, por ejemplo, las llamadas al sistema que fallan devuelven —l y ponen en una variable global
errno el código de error. La descripción del error se puede ver en el archivo /usr/include/sys/errno.h o
imprimirlo en pantalla mediante la función perrorO. A continuación, se muestran algunos códigos de error
de UNIX junto con sus descripciones

#define EPERNM 1 /* Not super-user */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* interrupted system cali */
#define ElO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /*k Arg iist too long */
#define ENOEXEC 8 /* Exec format error */
#define EBAOF 9 /* Bad file number */
En Windows se devuelven más códigos de error en las llamadas a función, e incluso en algunos
parámetros de las mismas. Igualmente, se puede obtener más información del error mediante la función
GetLastError ().

Uso de estándares

Proporcionar una interfaz de usuario estándar garantiza a los programadores la portabilidad de sus
aplicaciones, así como un comportamiento totalmente predecible de las llamadas al sistema en cuanto a
definición de sus prototipos y sus resultados. Actualmente, el único estándar definido para la interfaz de
sistemas operativos es POSIX (Portable Operating Systeni interface) [ 19881, basado principalmente en la
interfaz del sistema operativo UNIX. Todos los sistemas operativos modernos proporcionan este estándar
en su interfaz, bien como interfaz básica (en el caso de UNIX y LINUX) o bien como un subsistema POSIX
(caso de Windows) que se ejecuta sobre la interfaz básica (Win32).

ARQUITECTURA DEL SISTEMA DE ENTRADA/SALIDA

El sistema de entrada/salida está construido como un conjunto de manejadores apilados, cada uno de los
cuales está asociado a un dispositivo de entrada/salida (archivos, red, etc.). Ofrece a las aplicaciones y
entornos de ejecución servicios genéricos que permiten manejar los objetos de entrada/salida del sistema.
A través de ellos se puede acceder a todos los manejadores de archivos y de dispositivos tales como discos, cintas, redes, consola, tarjetas de sonido, etc.

Estructura y componentes del sistema de E/S.

La arquitectura del sistema de entrada/salida es compleja y está estructurada en capas, cada una
de las cuales tiene una funcionalidad bien definida:

•Interfaz del sistema operativo para entrada/salida. Proporciona servicios de E/S síncrona y
asíncrona a las aplicaciones y una interfaz homogénea para poderse comunicar con los manejadores
de dispositivo ocultando los detalles de bajo nivel.
• Sistemas de archivos. Proporcionan una interfaz homogénea, a través del sistema de archivos
virtuales, para acceder a todos los sistemas de archivos que proporciona el sistema operativo (FFS,
SV, NTFS, FAT, etc.). Permite acceder a los manejadores de los dispositivos de almacenamiento de forma transparente, incluyendo en muchos casos, como NFS o NTFS, accesos remotos a través de redes. En algunos sistemas, como Windows NT, los servidores para cada tipo de sistema de archivos se pueden cargar y descargar dinámicamente como cualquier otro manejador.
• Gestor de redes. Proporciona una interfaz homogénea para acceder a todos los sistemas de red que
proporciona el sistema operativo (TCP/IP, Novell, etc.). Además, permite acceder a  los manejadores de cada tipo de red particular de forma transparente.
• Gestor de bloques. Los sistemas de archivos y otros dispositivos lógicos con acceso a nivel de bloque se suelen limitar a traducir las operaciones del formato del usuario al de bloques que entiende el dispositivo y se las pasan a este gestor de bloques. El gestor de bloques admite únicamente operaciones a nivel de bloque e interacciona con la cache de bloques para optimizar la E/S.
• Gestor de cache. Optimiza la entrada/salida mediante la gestión de almacenamiento intermedio en
memoria para dispositivos de E/S de tipo bloque [ 1985]. Es importante saber que su tamaño varía
dinámicamente en función de la memoria RAM disponible y que los bloques se escriben a los
dispositivos según una política bien definida, que en UNIX y WINDOWS NT es la de escritura
retrasada.
• Manejadores de dispositivo. Proporcionan operaciones de alto nivel sobre los dispositivos y las
traducen en su ámbito interno a operaciones de control de cada dispositivo particular. Como ya se
ha dicho, los manejadores se comunican con los dispositivos reales mediante puertos o zonas de
memoria especiales.
Cada uno de los componentes anteriores se considera un objeto del sistema, por lo que habitualmente
todos los sistemas operativos permiten modificar el sistema operativo de forma estática o dinámica para
reemplazar, añadir o quitar manejadores de dispositivos. Sin embargo, habitualmente, y por razones de
seguridad, no se permite a las aplicaciones de usuario acceder directamente a los dispositivos, sino a través
de la interfaz de llamadas al sistema operativo.

Software de E/S

Este software se organiza en una serie de capas que se muestran en la Figura. Estas capas se corresponden, en general, con los niveles de la arquitectura de E/S.
Como puede verse en dicha figura, los procesos de usuario emiten peticiones de entrada/salida al
sistema operativo. Cuando un proceso solicita una operación de E/S, el sistema operativo prepara dicha
operación y bloquea al proceso hasta que se recibe una interrupción del controlador del dispositivo indicando que la operación está completa. Las peticiones se procesan de forma estructurada en las siguientes capas:
• Manejadores de interrupción.
• Manejadores de dispositivos o drivers.
• Software de EIS independiente de los dispositivos. Este software está formado por la parte de alto
nivel de los manejadores, el gestor de cache, el gestor de bloques y el servidor de archivos.
• Interfaz del sistema operativo. Llamadas al sistema que usan las aplicaciones de usuario.
El uso de capas conlleva la realización de varias copias de datos, alguna de las cuales son inevitables.
En algunos casos, la copia que se realiza en el núcleo del sistema operativo puede ser innecesaria, por lo
que existen mecanismos para acceder directamente a los controladores desde la interfaz de E/S del sistema
a los manejadores. Sin embargo, y como norma general, esa copia existe siempre.
El sistema operativo estructura el software de gestión de E/S de esta forma para ofrecer a los usuarios
una serie de servicios de E/S independientes de los dispositivos. Esta independencia implica que deben
emplearse los mismos servicios y operaciones de E/S para leer datos de un disquete, de un disco duro, de un CD-ROM o de un teclado, por ejemplo. Como se verá más adelante, el servicio read de POSIX puede
utilizarse para leer datos de cualquiera de los dispositivos citados anteriormente. Además, la estructuración
en capas permite hacer frente a la gestión de errores que se pueden producir en el acceso a los periféricos en el nivel de tratamiento más adecuado. A continuación, se describe más en detalle cada uno de los
componentes.

Manejadores de interrupción
Los manejadores de interrupción se encargan de tratar las interrupciones que generan los controladores de
dispositivos una vez que éstos están listos para la transferencia de datos o bien han leído o escrito los datos
de memoria principal en caso de acceso directo a memoria. Para tratar dicha interrupción se ejecuta el
correspondiente manejador de interrupción cuyo efecto es el de salvar los registros, comunicar el evento al
manejador del dispositivo y restaurar la ejecución de un proceso (que no tiene por qué ser el interrumpido).
En la sección anterior se mostró más en detalle cómo se trata una interrupción.

Los manejadores de interrupción suelen hacer algo más que comunicar el evento al manejador de
dispositivo. Cuando una interrupción ocurre muy frecuentemente, caso del reloj, o cuando la cantidad de
información a transferir es muy pequeña, caso del teclado, sería muy costoso comunicar siempre el evento
al manejador de dispositivo asociado. En estos casos, el propio manejador de interrupción registra la
ocurrencia del evento, bien mediante el incremento de una variable global para el reloj o la acumulación de
caracteres en un buffer del teclado. La notificación al manejador se hace únicamente cada cierto número de
ocurrencias del evento, en el caso del reloj, o activando unflag que indica que hay datos en el buffer del
teclado.

Manejadores de dispositivos
Cada dispositivo de E/S, o cada clase de dispositivos, tiene un manejador asociado en el sistema operativo.
Dicho manejador incluye: código independiente del dispositivo para proporcionar al nivel superior del
sistema operativo una interfaz de alto nivel y el código dependiente del dispositivo necesario para
programar el controlador del dispositivo a través de sus registros y mandatos. La tarea de un manejador de
dispositivo es aceptar peticiones en formato abstracto, de la parte del código de E/S independiente del
dispositivo, traducir dichas peticiones a términos que entienda el controlador, enviar al mismo las órdenes
adecuadas en la secuencia correcta y esperar a que se cumplan. La Figura 7.9 muestra un diagrama de flujo
con las operaciones de un manejador.

Todos los manejadores tienen una lista de peticiones pendientes por dispositivo donde se encolan las
peticiones que llegan de niveles superiores. El manejador explora la lista de peticiones, extrae una petición
pendiente y ordena su ejecución. La política de extracción de peticiones de la lista es dependiente de
manejador y puede ser FIFO, con pr etc. Una vez enviada la petición al controlador, el manejador se bloquea o no, dependiendo de la velocidad del dispositivo. Para los lentos (discos) se bloquea esperando una interrupción.
Para los rápidos (pantalla, discos RAM, etcétera) responde inmediatamente. Después de recibir el fin de
operación, controla la existencia de errores y devuelve al nivel superior el estado de terminación de la
operación. Si tiene operaciones pendientes en la cola de peticiones, atiende a la siguiente, en caso de que le
toque ejecutar después de la operación de E/S. En caso contrario se bloquea.

La mayor parte del sistema de E/S es software independiente de dispositivo. Como se puede ver en la
Figura anterior este nivel incluye el sistema de archivos y el de gestión de red, el gestor de bloques, la cache de bloques y una parte de los manejadores de dispositivo. La principal función de esta capa de software es
ejecutar las funciones de E/S que son comunes a todos los dispositivos a través de una interfaz uniforme,
Internamente, en este nivel se proporciona acceso a nivel de bloques o caracteres, almacenamiento
intermedio, gestión de los dispositivos, planificación de la E/S y control de errores.
El tamaño de acceso a nivel de bloques se hace usando tamaños de bloque de acceso comunes para
todo un sistema de archivos, lo que permite ocultar que cada dispositivo puede tener distinto tamaño de
sector y distinta geometría. Estos detalles quedan ocultos por la capa de software in dependiente de
dispositivo que ofrece una interfaz sobre la base de bloques lógicos del sistema de archivos. Lo mismo
ocurre con los dispositivos de caracteres, algunos de los cuales trabajan con un carácter cada vez, como el
teclado, mientras otros trabajan con flujos de caracteres, como el módem o las redes.
Para optimizar la E/S y para armonizar las peticiones de usuario, que pueden ser de cualquier tamaño,
con los bloques que maneja el sistema de archivos, el software de E/S proporciona almacenamiento
intermedio en memoria del sistema operativo. Esta facilidad se usa para tres cosas:
• Optimizar la E/S evitando accesos a los dispositivos.
• Ocultar las diferencias de velocidad con que cada dispositivo y usuario manejan los datos.
• Facilitar la implementación de la semántica de compartición, al existir una copia única de los datos
en memoria.

El sistema de E/S mantiene buffers en distintos componentes. Por ejemplo, en la parte del manejador
del teclado independiente del dispositivo existe un buffer para almacenar los caracteres que teclea el
usuario hasta que se pueden entregar a los niveles superiores. Si se usa una línea serie para leer datos de un
sistema remoto y almacenarlos en el disco, se puede usar un buffer para guardar temporalmente los datos
hasta que tengan una cierta entidad y sea rentable escribirlos a disco. Si se está leyendo o escribiendo un
archivo, se guardan copias de los bloques en memoria para no tener que acceder al disco si se vuelven a
leer.
La gestión de los dispositivos agrupa a su vez tres servicios: nombrado, protección y control de acceso.
El nombrado permite traducir los nombres de usuario a identificadores del sistema. Por ejemplo, en UNIX,
cada dispositivo tiene un nombre (p. ej.: /dev/cdrom) que se traduce en un único identificador interno (o
nodo-i), que a su vez se traduce en un único número de dispositivo principal (clase de dispositivo) y
secundario (elemento de la clase). Cada dispositivo tiene asociada una información de protección (en UNIX
mediante 3 bits para dueño, grupo y mundo) y este nivel de software asegura que los requisitos de
protección se cumplen. Además proporciona control de acceso para que un dispositivo dedicado, como una
impresora, sea accedido por un único usuario cada vez.
Una de las funciones principales del sistema de E/S es la planificación de la E/S de los distintos
componentes. Para ello se usan colas de peticiones para cada clase de dispositivo, de las que se extraen las
peticiones de cada dispositivo en particular. Cada una de estas colas se ordena siguiendo una política de
planificación, que puede ser distinta en cada nivel. Imagine el caso de LINUX, donde existe una cola global
de peticiones de E/S, ordenadas en orden FIFO, para los discos instalados. Cuando un manejador de disco
queda libre, busca la cola global para ver si hay peticiones para él y, si existen, las traslada a su cola de peticiones particular ordenadas según la política SCAN, por ejemplo. Este mecanismo permite optimizar la E/S al conceder a cada mecanismo la importancia que, a juicio de los diseñadores del sistema operativo, se merece. En el caso de Windows NT, por ejemplo, el ratón es el dispositivo de E/S más prioritario del sistema. La razón que hay detrás de esta política es conseguir un sistema muy interactivo. En otros sistemas, como UNIX, las operaciones de disco son más prioritarias que las del ratón para poder desbloquear rápidamente a los procesos que esperan por la E/S. Sea cual sea el criterio de planificación, todos los sistemas de E/S planifican las actividades en varios lugares.
Por último, este nivel proporciona gestión de errores para aquellos casos que el manejador de
dispositivo no puede solucionar. Un error transitorio de lectura de un bloque se resuelve en el manejador
reintentando su lectura. Un error permanente de lectura no puede ser resuelto y debe ser comunicado al
usuario para que tome las medidas adecuadas. En general, todos los sistemas operativos incluyen alguna
forma de control de errores internos y de notificación al exterior en caso de que esos errores no se puedan
resolver. Imagine, por ejemplo, que una aplicación quiere leer de un dispositivo que no existe. El sistema de
E/S verá que el dispositivo no está y lo notificará a los niveles superiores hasta que el error llegue a la
aplicación. Sin embargo, es importante resaltar que los sistemas operativos son cada vez más robustos y
cada vez incluyen más control y reparación de errores, para lo cual usan métodos de paridad, checksums,
códigos correctores de error, etc. Además, la información que proporcionan cuando hay un error es cada
vez mayor. En Windows NT, por ejemplo, existen monitores que permiten ver el comportamiento de las
operaciones de E/S.

CARACTERIZACIÓN DE LOS DISPOSITIVOS DE E/S

La visión del sistema de E/S puede ser muy distinta dependiendo del nivel de detalle necesario en su
estudio. Para los programadores, el sistema de E/S es una caja negra que lee y escribe datos en dispositivos
externos a través de una funcionalidad bien definida. Para los fabricantes de dispositi vos, un dispositivo es
un instrumento muy complejo que incluye cientos o miles de componentes electrónicos o electromecánicos.
Los diseñadores de sistemas operativos se encuentran en un lugar intermedio entre los dos anteriores. Les
interesa la funcionalidad del dispositivo, aunque a un nivel de detalle mucho más grande que la
funcionalidad que espera el programador de aplicaciones, pero también les interesa conocer la interfaz
física de los dispositivos y su comportamiento interno para poder optimizar los métodos de acceso a los
mismos.
En esta sección se estudia brevemente cómo se conecta un dispositivo de E/S a una computa dora y se
lleva a cabo una caracterización de los dispositivos de E/S según sus métodos y tamaño de acceso, su forma
de programación, etc.

Conexión de un dispositivo de E/S a una computadora

La Figura muestra el esquema general de conexión de periféricos a una computadora [De Miguel,
1998]. En el modelo de un periférico se distinguen dos elementos:
• Periféricos o dispositivos de E/S. Elementos que se conectan a la unidad central de proceso a
través de las unidades de entrada/salida. Son el componente mecánico que se conecta a la
computadora.
• Controladores de dispositivos o unidades de E/S. Se encargan de hacer la transferencia de
información entre la memoria principal y los periféricos. Son el componente electrónico a través
del cual se conecta el dispositivo de E/S. Tienen una conexión al bus de la computadora y otra para
el dispositivo (generalmente mediante cables internos o externos).

Los controladores son muy variados, casi tanto como los dispositivos de E/S. Muchos de ellos, como
los de disco, pueden controlar múltiples dispositivos. Otros, como los de canales de E/S, incluyen su propia
UCP y bus para controlar la E/S por programa y evitar interrupciones en la UCP de la computadora. De
cualquier forma, en los últimos años ha existido un esfuerzo importante de estandarización de los
dispositivos, lo que permite usar un mismo controlador para dispositivos de distintos fabricantes. Un buen
ejemplo lo constituyen los dispositivos SCSI (Small Computer System interface), cuyos controladores
ofrecen una interfaz común independientemente de que se trate de un disco, una cinta, un CD-ROM, etc.
Otro buen ejemplo son los controladores IDE (Integrated Drive Electronics), que suelen usarse para
conectar los discos en todas las computadoras personales. En cualquier caso, y sea como sea el controlador, su misión es convertir los datos del formato interno del dispositivo a uno externo que se ofrezca a través de una interfaz de programación bien definida.

El controlador es el componente más importante desde el punto de vista del sistema operativo, ya que
constituye la interfaz del dispositivo con el bus de la computadora y es el componente que se ve desde la
UCP. Su programación se lleva a cabo mediante una interfaz de muy bajo nivel que proporciona acceso a
una serie de registros del controlador, incluidos en el mapa de E/S de la computadora, que se pueden acceder mediante instrucciones de máquina de E/S. Hay tres registros importantes en casi todos los
controladores: registro de datos, estado y control. El registro de datos sirve para el intercambio de datos.
En él irá el controlador cargando los datos leídos y de él irá extrayendo los datos para su escritura en el
periférico. Un bit del registro de estado sirve para indicar que el controlador puede transferir una palabra.
En las operaciones de lectura esto significa que ha cargado en el registro de datos un nuevo valor, mientras
que en las de escritura significa que necesita un nuevo dato. Otros bits de este registro sirven para que el
controlador indique los problemas que ha encontrado en la ejecución de la última operación de E/S. El
registro de control sirve para indicarle al controlador las operaciones que ha de realizar. Los distintos bits
de este registro indican distintas acciones que ha de realizar el periférico. Para empezar una operación de
E/S, la UCP tiene que escribir sobre los registros anteriores los datos de la operación a través de una
dirección de E/S o de memoria asignada únicamente al controlador. Este modelo vale tanto para los
terminales o la pantalla como para los discos.
Las características del controlador son muy importantes, ya que definen el aspecto del periférico para
el sistema operativo. Atendiendo a las características del hardware de los dispositivos, se pueden observar
los siguientes aspectos distintivos:
• Dirección de E/S. En general hay dos modelos de direccionamiento de E/S, los que usan puertos y
los que proyectan los registros en memoria.
• Unidad de transferencia. Los dispositivos suelen usar unidades de transferencia de tamaño fijo.
Hay dos modelos clásicos de dispositivos: de caracteres y de bloques.
• Interacción computadora-controlador. La computadora tiene que interaccionar con la computadora para realizar las operaciones de E/S y saber cuándo terminan.

Dispositivos conectados por puertos o proyectados en memoria

Para empezar una operación de E/S, la UCP tiene que escribir sobre los registros anteriores los datos de la
operación a través de una dirección de E/S o de memoria asignada únicamente al controlador. Según se
haga de una u otra forma, se distingue entre dispositivos conectados por puertos o proyectados en memoria.
El modelo de dispositivos por puertos es clásico en las arquitecturas de Intel. En ellas, cuando se
instala un dispositivo, a su controlador se le asigna un puerto de E/S, una interrupción hardware y un vector de interrupción.
Para efectuar una operación de E/S la UCP ejecuta operaciones por o portout con la dirección de puerto del dispositivo y con parámetros para indicar qué registro se quiere manipular. Todas las operaciones de entrada/salida (pantalla gráfica, impresoras, ratón, discos, etc.) se realizan usando esas dos instrucciones de lenguaje máquina con los parámetros adecuados. El problema de este tipo de direccionamiento es que exige conocer las direcciones de E/S y programar las instrucciones especiales de E/S, lo que es significativamente distinto del modelo de memoria de la computadora.
El otro modelo de direccionamiento de E/S es el modelo proyectado en memoria. Este modelo, típico de las arquitecturas de Motorola, asigna a cada dispositivo de E/S un rango de direcciones de memoria a través de las cuales se escribe sobre los registros del controlador. En este modelo no hay instrucciones específicas de E/S, sino que las operaciones se llevan a cabo mediante instrucciones máquina de manejo de memoria, lo que permite gestionar un mapa único de direcciones de memoria. Sin embargo, para no tener conflictos con otros accesos a memoria y para optimizar las operaciones, se reserva una zona de memoria física para asignar las direcciones de E/S.

Dispositivos de bloques y de caracteres

Los dispositivos de almacenamiento secundario y terciario manejan la información en unidades de tamaño
fijo, denominadas bloques, por lo que a su vez se denominan dispositivos de bloques. Estos bloques se
pueden direccionar de manera independiente, lo que permite leer o escribir un bloque con independencia de
los demás. Los dispositivos de bloque lo son porque el hardware fuerza la existencia de accesos de un tamaño determinado. Un disco, por ejemplo, se divide en sectores de 512 bytes o de 1 KB, siendo un sector la unidad mínima de transferencia que el controlador del disco puede manejar.
Los dispositivos de caracteres, como los terminales, impresoras, tarjetas de red, módems, etcétera, no
almacenan información en bloques de tamaño fijo. Gestionan flujos de caracteres de forma lineal y sin
ningún tipo de estructura de bloque. Un teclado es un buen ejemplo de estos dispositivos. Está conectado a
una UART (Universal Asynchronous Receiver/Transmiter) que recibe un carácter del teclado cada vez que
se pulsa una tecla. No es posible leer un bloque de teclas de un golpe o buscar dentro del dispositivo por
ninguna unidad. Un terminal por línea serie también es un dispositivo de caracteres. Su controlador se
limita a enviar al periférico el flujo de caracteres que debe representar en la pantalla y a recibir del mismo
los caracteres tecleados por el usuario.

E/S programada o por interrupciones

Un controlador de dispositivo o unidad de E/S se encarga de controlar uno o más dispositivos de! mismo
tipo y de intercambiar información entre ellos y la memoria principal o unidad central de proceso de la
computadora. El controlador debe encargarse además de sincronizar la velocidad del procesador con la del
periférico y de detectar los posibles errores que se produzcan en el acceso a los periféricos. En el caso de un controlador de disco, éste debe encargarse de convertir un flujo de bits procedente del disco a un bloque de bytes detectando y corrigiendo, si es posible, los errores que se produzcan en esta transferencia. Una vez
obtenido el bloque y comprobado que se encuentra libre de errores, deberá encargarse de transferirlo a
memoria principal.

La información entre los controladores de dispositivo y la unidad central de proceso o memoria principal se puede transferir mediante un programa que ejecuta continuamente y lee o escribe los datos del (al) controlador. Con esta técnica, que se denomina E/S programada, la transferencia de información entre un periférico y el procesador se realiza mediante la ejecución de una instrucción de E/S. Con esta técnica,
es el procesador el responsable de extraer o enviar datos entre el procesador y el controlador de dispositivo, lo que provoca que el procesador tenga que esperar mientras se realiza la transferencia entre el periférico y el controlador. Dado que los periféricos son sensiblemente más lentos que el procesador, éste deberá esperar una gran cantidad de tiempo hasta que se complete la operación de E/S. En este caso no existe ningún tipo de concurrencia entre la E/S y el procesador ya que éste debe esperar a que finalice la
operación.
Aunque esta técnica es muy antigua, ya que proviene del tiempo en que los controladores no tenían
interrupciones, actualmente los canales de E/S y algunos multiprocesadores usan esta técnica para evitar
que lleguen a la UCP de la computadora muchas interrupciones de E/S. En ambos casos, la técnica es la
misma: dedicar una UCP especial para la E/S. La forma de hacerlo es muestrear continuamente los
registros de estado de los controladores para ver si están disponibles y, en ese caso, leer o escribir los
registros. Imagine un canal de E/S al que hay conectados múltiples buses de E/S que, a su vez, tienen
múltiples dispositivos de E/S. Si la UCP quiere escribir en uno de ellos, debe mirar su registro de estado
hasta que los bits indiquen que no está ocupado. Cuando esto ocurra, escribirá un bloque en los registros del
controlador y esperará hasta que los bits de estado indiquen que está disponible. Imagine que quiere leer de
otro controlador, deberá esperar a que los bits de estado le indiquen que está disponible, programar la
operación y esperar a que se indique que los datos están disponibles. Evidentemente, incluso aunque la
UCP esté controlando varios dispositivos de E/S, siempre existe pérdida de ciclos debido a la existencia de
las esperas. Sin embargo, existen situaciones en que esto no es así. En algunos sistemas de tiempo real,
como por ejemplo un satélite, la velocidad de E/S es tan rápida (byte/microsegundos) que sería imposible efectuarla con interrupciones, debido al coste de tratar cada interrupción. En estos casos, la E/S programada es la técnica de elección.

Con E/S programada el procesador tiene que esperar hasta que el controlador esté listo para recibir o
enviar datos, y mientras tanto no realiza ningún trabajo útil. Empleando E/S dirigida por interrupciones el
procesador envía la orden de E/S al controlador de dispositivo y no espera a que éste se encuentre listo para enviar o transmitir los datos, sino que se dedica a otras tareas hasta que llega una interrupción del
dispositivo que indica que se ha realizado la operación solicitada.
El modelo de interrupciones está íntimamente ligado a la arquitectura del procesador. Casi todas las
UCP actuales incluyen interrupciones vectorizadas y enmascarables. Es decir, un rango de interrupciones
entre 0 y 255, por ejemplo, alguna de las cuales se pueden inhibir temporalmente para no recibir
interrupciones de su vector correspondiente. Cada interrupción se asigna a un dispositivo, o un rango de
ellos en caso de un controlador SCSI o una cadena de dispositivos tipo daisv chain, que usa el vector
correspondiente para indicar eventos de E/S a la UCP. Cuando se programa una operación en un
dispositivo, como por ejemplo una búsqueda en un disco, éste contesta con un ACK indicando que la ha
recibido, lo que no significa que haya terminado. En este caso existe concurrencia entre la E/S y el
procesador, puesto que éste se puede dedicar a ejecutar código de otro proceso, optimizando de esta forma el uso del procesador. Al cabo de un cierto tiempo, cuando el disco ha efectuado la búsqueda y las cabezas del disco están sobre la posición deseada, genera una interrupción (poniendo un 1 en el vector
correspondiente). La rutina de tratamiento de la interrupción se encargará de leer o enviar el dato al
controlador. Obsérvese que tanto la tabla de interrupciones como la rutina de tratamiento de la interrupción
se consideran parte del sistema operativo. Esto suele ser así por razones de seguridad; en concreto, para
evitar que los programas que ejecuta un usuario puedan perjudicar a los datos o programas de otros
usuarios.
Las computadoras incluyen varias señales de solicitud de interrupción, cada una de las cuales tiene una
determinada prioridad. En caso de activarse al tiempo varias de estas señales, se tratará la de mayor
prioridad, quedando las demás a la espera de ser atendidas. Además, la computadora incluye un mecanismo
de inhibición selectiva que permite detener todas o determinadas señales de interrupción. Las señales
inhibidas no son atendidas hasta que pasen a estar desinhibidas. La información de inhibición de las
interrupciones suele incluirse en la parte del registro de estado que solamente es modificable en nivel de
núcleo, por lo que su modificación queda restringida al sistema operativo.
¿Quién asigna las interrupciones a los dispositivos? Normalmente, el sistema operativo se hace cargo de
esa asignación cuando instala el dispositivo. Ahora bien, también suele existir la posibilidad de que el
administrador fije las interrupciones manualmente.

Nunca asigne interrupciones manualmente si no tiene experiencia con el sistema
operativo y la arquitectura de la computadora. Si origina conflictos entre
interrupciones, varios dispositivos usarán el mismo

¿ Quien proporciona la rutina de tratamiento de interrupción? Las rutinas de nterrupc suelen tener
dos partes: una genérica y otra particular para el dispositivo.La parte genérica permite:
1. Capturar la interrupción.
2. Salvaguardar el estado del procesador.
3. Activar la rutina de manejo de la interrupción.
4. Indicar al planificador que debe poner lista para ejecutar la rutina particular.
5. Desactivar la interrupción.
6. Restaurar el estado del procesador.
7. Ceder el control (RETI).
La rutina de tratamiento particular indica al planificador que encole la rutina particular, que se activa
cuando le llega su turno de planificación, posiblemente más tarde. La rutina genérica la proporciona el
sistema operativo y es independiente del dispositivo. Se limita a preparar el entorno de ejecución de la
interrupción, salvar los datos y parámetros, llamar a la rutina particular del manejador y restaurar el estado
del proceso. La rutina particular la proporciona el fabricante del dispositivo o del sistema operativo, si se
trata de un dispositivo estándar. Cuando se compra un dispositivo de E/S, como por ejemplo un ratón, es
habitual encontrar un disquete o un CD-ROM con los manejadores del dispositivo. El usuario o el
administrador debe instalar estos manejadores en el sistema operativo y reiniciarlo antes de que sea posible
acceder al dispositivo.

Es importante desactivar las interrupciones después de activar su tratamiento para evitar que
se presenten nuevas interrupciones antes de terminar el tratamiento y perder alguna de ellas.

Un caso especial en la arquitectura Intel es la controladora gráfica, que se encarga de gestionar la salida
a los dispositivos de mapas de bits (pantallas gráficas). Estas controladoras suelen tener su propia memoria,
sobre la cual se llevan a cabo las operaciones de E/S. Aunque la memoria de la controladora se escribe
también a partir de un puerto de E/S, sus prestaciones son muy altas (en nosegundos), por lo que el
tratamiento de las operaciones de E/S se desvía del estándar en el sistema operativo, ya que estos
dispositivos no interrumpen, por lo que se efectúa E/S programada.

Mecanismos de incremento de prestaciones

A medida que la tecnología de fabricación de controladores ha ido mejorando, la capacidad de efectuar
operaciones autónomas en los mismos se ha incrementado considerablemente. Actualmente es muy
frecuente que un controlador de dispositivo tenga capacidad de procesamiento, memoria interna (hasta 16
MB en controladoras gráficas, por ejemplo) y capacidad de solapar búsquedas en unos dispositivos con
transferencias en otros. Estas mejoras convierten al controlador en un auténtico procesador intermedio
entre la UCP y el dispositivo, lo que le permite proporcionar varios servicios para incrementar las
prestaciones de E/S del dispositivo. En esta sección se comentan los más importantes.

Acceso directo a memoria
Tanto en la E/S programada como la basada en interrupciones, la UCP debe encargarse de la transferencia
de datos una vez que sabe que hay datos disponibles en el controlador. Una mejora importante para
incrementar la concurrencia entre la UCP y la E/S consiste en que el controlador del dispositivo se pueda
encargar de efectuar la transferencia de datos, liberando de este trabajo a la UCP, e interrumpir a la UCP
sólo cuando haya terminado la operación completa de E/S. Esta técnica se denomina acceso directo a
memoria (DMA, Direct Memory Access).
Cuando se utiliza acceso directo a memoria, es el controlador el que se encarga directamente de
transferir los datos entre el periférico y la memoria principal, sin requerir intervención alguna por parte del
procesador.

Esta técnica funciona de la siguiente manera: cuando el procesador desea I Qe un bloque de datos, envía una orden al controlador indicándole la siguiente información:
• Tipo de operación: lectura o escritura.
• Periférico involucrado en la operación.
• La dirección de memoria desde la que se va a leer o a la que va a escribir directamente al
controlador de dispositivo (dirección).
• El número de bytes a transferir (contador).

Una vez emitida la orden, el procesador continúa realizando otro trabajo sin necesidad de transferir el
bloque de datos. Es el propio controlador el que se encarga de transferir el bloque de datos del periférico a
memoria. La transferencia se realiza palabra a palabra. Cuando el controlador ha completado la
transferencia, genera una interrupción que activa la rutina de tratamiento correspondiente, de tal manera
que se sepa que la operación ha concluido.
Utilizando acceso directo a memoria el procesador únicamente se ve involucrado al inicio y al final de
la transferencia. Por tanto, cuando el sistema operativo despierta al proceso que pidió la E/S, no tiene que
copiar el bloque a memoria porque ya está allí. El DMA requiere una etapa de almacenamiento intermedio
en el controlador del dispositivo para armonizar la velocidad del dispositivo de E/S con la copia de los
datos en memoria principal. La razón para este almacenamiento intermedio reside en que una vez
que el dispositivo empieza la transferencia de datos, ésta debe hacerse a velocidad constante para evitar
transferencias parciales y nuevas esperas de posicionamiento del dispositivo sobre los datos (latencia). Una
vez transferidos los datos a la memoria del controlador, éste los copia en memoria principal aprovechando
el ancho de banda libre del bus.

Los pasos a seguir en una operación de E/S con DMA son los siguientes:
1. Programación de la operación de E/S. Se indica al controlador la operación, los datos a transferir y
la dirección de memoria sobre la que se efectuará la operación.
2. El controlador contesta aceptando la petición de E/S.
3. El controlador le ordena al dispositivo que lea (para operación de lectura) una cierta cantidad de datos desde una posición determinada del dispositivo a su memoria interna.
4. Cuando los datos están listos, el controlador los copia a la posición de memoria que tiene en sus
registros, incrementa dicha posición de memoria y decrementa el contador de datos pendientes de
transferir.
5. Los pasos 3 y 4 se repiten hasta que no quedan más datos por leer.
6. Cuando el registro de contador está a cero, el controlador interrumpe a la UCP para indicar que la
operación de DMA ha terminado.

Canales de E/S con DMA

Un canal de E/S se puede mejorar si se incluye el concepto de DMA que permite al controlador ejecutar
instrucciones de E/S. Con estos sistemas, las instrucciones de E/S se almacenan en memoria principal y
son ejecutadas ordenando al procesador del canal que ejecute un programa en memoria. Dicho programa se
encarga de designar dispositivos y zonas de memoria de E/S.
Hay dos tipos principales de canales de E/S: canal selector y canal multiplexor. Ambos pueden
interaccionar con varios dispositivos de E/S, pero mientras el canal selector sólo puede transferir datos de
un dispositivo a la vez, el canal multiplexor puede transferir datos de varios dispositivos simultáneamente.

Caches de disco en el controlador

Las caches de datos, tan populares en sistemas operativos, han irrumpido en el mundo de los controladores
de disco con mucha fuerza. La idea es aprovechar la memoria interna de los controladores para leer los
datos por adelantado, evitando muchas operaciones de búsqueda en el disco y sobre todo los tiempos de
latencia necesarios para esperar a que los datos pasen de nuevo bajo las cabezas del disco [Biswas, 19931.
La proximidad espacial permite optimizar la E/S en el ámbito de controlador, ya que en lugar de leer un
sector, o un grupo de ellos, se leen pistas enteras en cada vuelta de disco, lo que permite traer múltiples
bloques de datos en una única operación. En los canales de E/S, donde suele haber mucha memoria interna,
se guardan en memoria varias pistas por cada dispositivo de E/S.
Estos mecanismos permiten optimizar mucho la E/S, especialmente en operaciones de lectura con un
comportamiento conocido. Para evitar afectar al rendimiento de las operaciones que no responden a
patrones de proximidad espacial predecibles, los controladores incluyen instrucciones para desactivar este
mecanismo, siempre que el sistema operativo lo crea conveniente.
Solapamiento de búsquedas y transferencias
Los controladores de disco actuales permiten la conexión de varios dispositivos de E/S y tienen un canal de
comunicaciones con ellos de varios MB. Un controlador SCSI-2 permite conectar hasta ocho dispositivos y
tiene un ancho de banda de 40 MB/segundo. Un problema grave de los dispositivos es que las operaciones
de búsqueda son lentas y, mientras el controlador espera la respuesta, el bus de comunicaciones está vacío
porque no está siendo usado por ningún dispositivo.
Para optimizar el uso del conjunto de los dispositivos, muchos controladores actuales programan las
operaciones de búsqueda en los dispositivos y mientras reciben la respuesta transfieren datos de otros
dispositivos listos para leer o escribir. De esta forma existe paralelismo real entre los dispositivos, lo que
permite explotar al máximo el canal de comunicaciones. ¿Cómo sabe el controlador cuándo ha terminado
la espera? Pues con un sistema similar al de la E/S no bloqueante: programa un temporizador y cuando
vence le pregunta al dispositivo si ya está listo para transmitir.

Resumen. Entrada/Salida en sistemas operativos

En este blog se caracterizan los componentes que constituyen el hardware de E/S de una computadora,
se define la arquitectura del sistema de E/S de una computadora y se estudian algunos de los componentes
más importantes del sistema de E/S, tales como los sistemas de almacenamiento secundario y terciario, los terminales, los relojes, los dispositivos de red, etc. Para terminar se muestran los servicios de E/S más habituales en sistemas operativos, con ejemplos de programación que involucran llamadas al sistema de E/S.

El corazón de una computadora lo constituye la UCP. Esta unidad se encarga de procesar los datos y las
instrucciones para conseguir el fin deseado por una aplicación. Ahora bien, esta unidad no serviría de nada
sin otros dispositivos que almacenaran los datos y que permitieran interactuar con los usuarios y los
programadores de las computadoras. Los primeros son básicamente dispositivos de almacenamiento
secundario (discos) y terciario (cintas y sistemas de archivo). Los segundos son los denominados
dispositivos periféricos de interfaz de usuario, porque generalmente están fuera de la computadora y se
conectan a ella mediante cables, y son los teclados, ratones, micrófonos, cámaras y cualquier otro
dispositivo de E/S que se le ocurra conectar a una computadora.


Todos estos dispositivos de E/S se pueden agrupar en tres grandes grupos:
• Dispositivos de interfaz de usuario. Se llama así a los dispositivos que permiten la comunicación
entre los usuarios y la computadora. Dentro de este grupo se incluyen todos los dispositivos que sirven
para proporcionar interfaz con el usuario, tanto para entrada (ratón, teclado, etc.) como para salida
(impresoras, pantalla, etc.). Existen periféricos menos habituales, pero más sofisticados, tales como
un escáner, lectores de huella digital, lectores de cinta magnética, instrumentos musicales digitales
(MIDI), etc.
• Dispositivos de almacenamiento. Se usan para proporcionar almacenamiento no volátil de datos y
memoria. Su función primordial es abastecer de datos y almacenamiento a los programas que se
ejecutan en la UCP. Según su capacidad y la inmediatez con que se puede acceder a los datos
almacenados en estos dispositivos, se pueden dividir en almacenamiento secundario (discos y
disquetes) y terciario (cintas).
• Dispositivos de comunicaciones. Permiten conectar a la computadora con otras computadoras a
través de una red. Los dos tipos de dispositivos más importantes de esta clase son los módem, para comunicación vía red telefónica, y las tarjetas de interfaz a la red, para conectar la computadora a una red de área local.
El gran problema de todos estos dispositivos de E/S es que son muy lentos. Piense que mientras la UCP
procesa instrucciones a casi 1 GHz y la memoria RAM tiene un tiempo de acceso de nanosegundos, los
dispositivos de E/S más rápidos tienen una velocidad de acceso del orden de milisegundos.

Esta diferencia en la velocidad de acceso, y el hecho de que las aplicaciones son cada vez más interactivas y necesitan más E/S, hace que los sistemas de E/S sean el cuello de botella más importante de los sistemas de
computación y que todos los sistemas operativos dediquen un gran esfuerzo a desarrollar y optimizar todos
los mecanismos de E/S. Piense, por ejemplo, que el mero hecho de seguir el curso de un ratón supone
inspeccionar su posición varias veces por segundo. Igualmente, los dispositivos de comunicaciones
interrumpen continuamente el flujo de ejecución de la UCP para comunicar la llegada de paquetes de datos.
El sistema de E/S es la parte del sistema operativo que se ocupa de facilitar el manejo de los dispositivos de
EIS ofreciendo una visión lógica simplificada de los mismos que pueda ser usada por otros componentes
del sistema operativo (como el sistema de archivos) o incluso por el usuario. Mediante esta visión lógica se
ofrece a los usuarios un mecanismo de abstracción que oculta todos los detalles relacionados con los
dispositivos físicos, así como del funcionamiento real de los mismos. El sistema operativo debe controlar
el funcionamiento de todos los dispositivos de EIS para alcanzar los siguientes objetivos:
• Facilitar el manejo de los dispositivos de E/S. Para ello debe ofrecer una interfaz entre los
dispositivos y el resto del sistema que sea sencilla y fácil de utilizar.
• Optimizar la E/S del sistema, proporcionando mecanismos de incremento de prestaciones donde
sea necesario.
• Proporcionar dispositivos virtuales que permitan conectar cualquier tipo de dispositivo físico sin
que sea necesario remodelar el sistema de E/S del sistema operativo.
• Permitir la conexión de dispositivos nuevos de E/S, solventando de forma automática su instalación
usando mecanismos del tipo plug&play.

Sistemas operativos. Una visión aplicada - Jesús Carretero.