Módulo 3: Estructura de los Sistemas Operativos. 1. Módulos de los Sistemas Operativos. Un Sistema Operativo proporciona el entorno dentro del cual se ejecutan los programas. Para construir este entorno, es necesario dividir el sistema operativo en módulos y crear unas interfaces bien definidas para que los programas de usuario puedan interactuar con ellos. Internamente, los sistemas operativos varían mucho en su estructura, organizándose de acuerdo con diferentes esquemas. El diseño de un nuevo sistema operativo es una tarea muy complicada y de gran magnitud, y antes de iniciarlo es importante definir bien los objetivos del sistema. Es importante tener claro el tipo de sistema que se desea para poder elegir entre los distintos algoritmos y estrategias que se necesitarán. 1.1. Componentes del sistema. Como se ha dicho antes, los sistemas operativos son sistemas muy grandes y complejos: sólo podemos crear un sistema operativo dividiéndolo en fragmentos más pequeños. Cada uno de éstos debe ser una parte bien definida del sistema que tenga su función, sus entradas y sus salidas perfectamente definidas. No todos los sistemas tienen la misma estructura, pero la gran parte de los sistemas operativos que existen actualmente utilizan la estructura de componentes que se presenta en los siguientes puntos del temario. 1.1.1. Administración de procesos. La CPU ejecuta un gran número de programas, estos programas pueden ser, o bien aplicaciones que utiliza el usuario del sistema, u otro tipo de programas que son necesarios para el buen funcionamiento del sistema. Las actividades que realiza el sistema se denominan procesos. Un proceso es un programa en ejecución. Típicamente, un trabajo por lotes es un proceso, como también lo son un programa de usuario de tiempo compartido y una tarea de sistema. Básicamente, un proceso puede considerarse como un trabajo o un programa de tiempo compartido. En general, un proceso necesita determinados recursos para su ejecución, entre los que se encuentran el tiempo de CPU necesario para su ejecución, la memoria, los archivos y los dispositivos de E/S. Estos recursos se le asignan al proceso al crearlo, o mientras se realiza su ejecución a medida que el proceso los va necesitando. Un programa en sí, no se puede considerar como un proceso; un programa es una entidad pasiva, como el contenido de un archivo que se almacena en disco, mientras que un proceso es una entidad activa. Según esto, un proceso se puede entender como un programa en ejecución. La ejecución de un proceso debe efectuarse secuencialmente, es decir, en cualquier momento se ejecuta como máximo una instrucción del proceso. Así, aunque existan dos procesos asociados a un mismo programa, se consideran como dos secuencias de ejecución separadas. Es frecuente que los programas generen varios procesos durante su ejecución. Cada uno de los procesos funciona como una entidad independiente, aunque llegado el momento pueden comunicarse entre ellos. El Sistema Operativo es el encargado de proporcionar métodos para que los procesos se comuniquen entre si. Un proceso es la unidad de trabajo de un sistema. Dicho sistema consiste en un conjunto de procesos que se ejecutan simultáneamente. Se puede hablar de dos tipos de procesos, aquellos que son procesos del propio sistema operativo (aquellos que ejecutan código del sistema) y los procesos de usuario (aquellos que ejecutan Curso: Sistemas Operativos Multiusuario. 1 Módulo 3: Estructura de los Sistemas Operativos. código del usuario). Potencialmente, todos estos procesos pueden ejecutarse en forma concurrente, es decir, compartiendo el uso de la CPU entre ellos. El sistema operativo es responsable de las siguientes actividades relacionadas con la administración de procesos: • Crear y eliminar los procesos de usuario y del sistema. • Suspender y reanudar la ejecución de los procesos. • Proporcionar mecanismos para la sincronización de procesos. • Proporcionar mecanismos para la comunicación de procesos. • Proporcionar mecanismos para el manejo de bloqueos mutuos. 1.1.2. Administración de la memoria principal. La memoria es parte central del funcionamiento de un sistema de computación moderno. La memoria principal de un computador consiste en un gran vector de palabras o bytes, cada uno con su propia dirección (la dirección de memoria). A la memoria principal acceden tanto la CPU como los dispositivos de E/S. El procesador central lee las instrucciones de la memoria principal durante la ejecución de los programas; lo mismo sucede con los datos que utilizan dichos programas, se leen y se escriben en la memoria. La E/S realizada mediante DMA (vista en el módulo anterior) también lee y escribe los datos en la memoria. Para ejecutar los programas de usuario, el primer paso es almacenarlos en la memoria principal del computador. Una vez que, tanto los datos del programa como las instrucciones que los componen estén ocupando posiciones físicas de memoria (direcciones absolutas), la CPU ya puede utilizar esa información. Finalmente al terminar el programa, el espacio de memoria que ocupaba se libera, pudiendo ser utilizado por otro programa. Para mejorar la utilización de la CPU y la velocidad de respuesta del computador a los usuarios, se necesita conservar varios programas, datos e instrucciones, en memoria. Hoy en día, existen diferentes esquemas para la administración de memoria principal de un computador, la eficacia de los distintos algoritmos depende de la situación particular, pero sobre todo del diseño del hardware del sistema. Cada algoritmo requiere su propio apoyo del hardware. Todo lo que se refiere a administración de memoria se verá detenidamente en el próximo módulo. El sistema operativo es responsable relacionadas con la administración de memoria: • • • de las siguientes actividades Llevar un control de cuáles son las zonas de la memoria que se están usando y quién las usa. Decidir qué procesos se cargarán en memoria cuando haya espacio disponible. Asignar y recuperar el espacio en memoria según se requiera. 1.1.3. Administración del almacenamiento secundario. El objetivo principal de un sistema de computación es ejecutar programas, los cuales, junto con los datos a los que tienen acceso, deben encontrarse en la memoria principal durante su ejecución. El problema es que el tamaño de la memoria principal es demasiado pequeño para poder almacenar todos lo datos y Curso: Sistemas Operativos Multiusuario. 2 Módulo 3: Estructura de los Sistemas Operativos. todas las instrucciones de los programas, por lo que es necesario que el sistema proporcione un soporte diferente para poder almacenar toda esa información, este soporte es lo que se conoce como almacenamiento secundario. La mayoría de los sistemas de computación modernos utilizan discos como principal medio de almacenamiento, tanto para programas como para datos. La mayor parte de los programas se almacenan en disco hasta que se cargan en la memoria, y luego utilizan el disco como fuente y destino de su actividad. Por tanto, la adecuada administración del almacenamiento en disco tiene una importancia decisiva para el sistema de computación. El sistema operativo es responsable relacionadas con la administración de discos: • • • de las siguientes actividades Administración del espacio libre. Asignación del almacenamiento. Planificación de las operaciones sobre el disco. 1.1.4. Administración del sistema de E/S. El Sistema Operativo tiene que ocultar a los usuarios las particularidades de los distintos dispositivos hardware. Por ejemplo, en UNIX, las particularidades de los dispositivos de E/S se ocultan del resto del sistema operativo por medio de un sistema de E/S, el cual consiste en: • • • Un sistema de memoria caché mediante buffers. Una interfaz general con los manejadores de dispositivos. Manejadores para dispositivos de hardware específicos. Sólo el manejador del dispositivo conoce las particularidades del dispositivo al cual está asignado. 1.1.5 Administración de archivos. La información utilizada por los computadores se puede almacenar en distintos tipos de dispositivos físicos. Pero las características particulares de cada uno de ellos haría que su uso fuera muy complicado, habría que conocer cómo funciona y que estructura tiene cada uno de los dispositivos. Es competencia del Sistema Operativo, crear una perspectiva lógica común para utilizar todos los dispositivos, ocultando las particulares de cada uno de ellos al usuario. El sistema operativo se vale de las propiedades físicas de sus dispositivos de almacenamiento para definir una unidad de almacenamiento lógico, el archivo (o fichero). Por medio del Sistema Operativo, los archivos se relacionan con dispositivos físicos. Un archivo es un conjunto de información relacionada. Comúnmente, los archivos representan programas y datos. Los archivos de datos pueden ser numéricos, alfabéticos o alfanuméricos. Y pueden tener un formato libre, como los archivos de texto, o un formato rígido. Por lo general, un archivo es una secuencia de bits, bytes, líneas o registros, cuyo significado ha sido definido por el programador. El Sistema Operativo utiliza los archivos para administrar los dispositivos de almacenamiento masivo, comúnmente utilizados en los sistemas de computación: cintas, discos,... El Sistema Operativo es el encargado de organizar la información que se almacena en dichos dispositivos. En este sentido, y relacionado con el Curso: Sistemas Operativos Multiusuario. 3 Módulo 3: Estructura de los Sistemas Operativos. concepto de archivo, están los directorios, que son una forma de englobar distintos archivos que están relacionados. Otra función del Sistema Operativo, relacionada con la administración de archivos, es la del control de acceso a los mismos. Normalmente, los sistemas de computación son usados por distintos usuarios, es necesario que el Sistema Operativo controle el acceso de dichos usuarios a los archivos que se almacenan en los dispositivos del sistema. En resumen, el sistema operativo es responsable de las siguientes actividades relacionadas con la administración de archivos: • • • • • La creación y eliminación de archivos. La creación y eliminación de directorios. El manejo de operaciones primitivas para manipular archivos y directorios. La correspondencia entre archivos y almacenamiento secundario. La copia de seguridad de archivos en medios de almacenamiento estables. 1.1.6. Sistemas de protección. El Sistema Operativo es el encargado de asegurar que todo el sistema funcione correctamente. Por tanto, es indispensable que el propio sistema implemente elementos de seguridad que permitan proteger los distintos elementos que forman parte del sistema. El Sistema Operativo tienen que proporcionar mecanismos para asegurar que los archivos, segmentos de memoria, CPU y otros recursos puedan ser usados únicamente por aquellos procesos que han recibido la correspondiente autorización del sistema operativo y que los usen correctamente. Por ejemplo, el hardware de direccionamiento a memoria asegura que un proceso sólo puede trabajar dentro de su espacio de direcciones. El cronómetro asegura que ningún proceso pueda obtener el control de la CPU sin perderlo eventualmente. Por último, no se permite que los usuarios realicen por su cuenta sus operaciones de E/S, para proteger así la integridad de los dispositivos periféricos. La protección se refiere a un mecanismo para controlar el acceso de los programas, procesos o usuarios, a los recursos definidos por el sistema de computación. Este mecanismo debe ofrecer un medio para especificar los controles que se impondrán, junto con la manera de ponerlos en práctica. Un sistema orientado hacia la protección ofrece una forma de distinguir entre el uso autorizado y el no autorizado. 1.1.7. Redes. Hoy en día, el uso de redes de ordenadores está muy extendido, con todos los beneficios que nos proporcionan: compartición de recursos, reducción de costes, acceso a información en computadores remotos,... Los Sistema Operativos actuales tienen que proporcionar los recursos necesarios para la utilización de las redes de computadores. Los computadores independientes de antaño, han evolucionado a sistemas más complejos que se comunican entre ellos. Un sistema distribuido es un conjunto de procesadores que no comparten memoria ni reloj, pues cada uno tiene su propia memoria y los procesos se comunican entre sí a través de diversos medios, como canales de alta velocidad o líneas telefónicas. Los procesadores de un sistema distribuido pueden variar en tamaño y función, e incluyen pequeños Curso: Sistemas Operativos Multiusuario. 4 Módulo 3: Estructura de los Sistemas Operativos. microprocesadores, estaciones de trabajo, minicomputadores y grandes sistemas de computación de propósito general. Los procesadores del sistema se conectan a través de una red de comunicaciones, que puede configurarse de varias maneras y conectarse total o parcialmente. El diseño de la red de comunicaciones debe considerar las estrategias de conexión y encaminamiento, y los problemas de contiendas y seguridad. Un sistema distribuido permite al usuario el acceso a los diversos recursos que mantiene el sistema. El acceso a un recurso compartido hace posible aumentar la velocidad de los cálculos, ampliar la disponibilidad de datos y mejorar la confiabilidad. Los sistemas operativos usualmente generalizan el acceso a la red como una forma de acceso a archivos, con los detalles de la red contemplados en el manejador de la interfaz de la red. 1.1.8. Sistema intérprete de mandatos. Uno de los programas más importantes para un sistema operativo es el intérprete de mandatos. Este programa es el que se encarga de comunicar al usuario con el Sistema Operativo, es la forma que tienen los usuarios para comunicar sus instrucciones, lo que desean hacer, a la máquina. Algunos sistemas operativos, en especial los de microcomputadores, como MS-DOS y Apple Macintosh, incluyen al intérprete de mandatos en su núcleo. Otros sistemas operativos, sobre todo en las computadoras de gran tamaño, tratan al intérprete de mandatos como un programa especial que se ejecuta al iniciar un trabajo o cuando el usuario se conecta por primera vez al sistema. Los usuarios proporcionan sus instrucciones al Sistema Operativo utilizando los enunciados de control. Cuando se inicia un nuevo trabajo en un sistema por lotes, o cuando el usuario se conecta a un sistema de tiempo compartido, automáticamente se ejecuta un programa que lee e interpreta enunciados de control. A estos programas se les conoce con diversos nombres: intérprete de tarjetas de control, intérprete de línea de mandatos, shell (en UNIX), etc. Su función es bastante sencilla: obtener el siguiente enunciado de mandato y ejecutarlo. Los sistemas operativos suelen diferenciarse en la faceta de interpretación de mandatos. Es importante que el programa que se utilice para recibir los comandos del usuario sea sencillo y fácil de usar. Las diferencias que existen entre unos intérpretes y otros hacen que el sistema sea visto por el usuario de una manera más amable. Un ejemplo de esta situación son los intérpretes de mandatos de Macintosh o Windows, sistemas basados en menús y ventanas que se utilizan casi exclusivamente mediante un ratón. Existen otros intérpretes más complejos y difíciles de aprender que atraen a otros usuarios con requisitos también complejos. En este tipo de intérpretes, los mandatos se introducen mediante un teclado y se presentan en un terminal de pantalla o de impresión, usando la tecla de entrada (o retorno) para indicar que el mandato está completo y listo para ser ejecutado. Los shells UNIX trabajan de este modo. Los enunciados de mandato se encargan de la administración de procesos, manejo de E/S, administración del almacenamiento secundario, administración de la memoria principal, acceso al sistema de archivos, protección, redes y, en general, del control de todo el sistema. 1.2. Servicios del sistema operativo. Curso: Sistemas Operativos Multiusuario. 5 Módulo 3: Estructura de los Sistemas Operativos. Un sistema operativo proporciona el entorno necesario para la ejecución de programas. El sistema operativo ofrece varios servicios para los programadores para facilitar la tarea de programar. Los servicios que ofrecen los Sistemas Operativos varían de unos a otros, pero existen ciertos servicios que suelen ser comunes a la gran parte de los sistemas actuales. • • • • • Ejecución de programas. El Sistema Operativo tiene que ser capaz de ejecutar los programas y, por tanto, realizar todas las operaciones necesarias para que la ejecución sea posible. Operaciones de E/S. Los programas que se ejecutan en los computadores pueden requerir, llegado el momento, realizar operaciones de E/S. Debido a que los programas no las pueden realizar directamente, el Sistema Operativo tiene que ofrecer alguna manera de poder llevarlas a cabo. Manipulación del sistema de archivos. Es obvio que los programas que se ejecutan en las computadoras necesitan leer y escribir archivos, así como crearlos y eliminarlos. El Sistema Operativo debe de proporcionar todos los servicios necesarios para que estas operaciones se realicen de la forma más sencilla posible. Comunicaciones. La comunicación entre los distintos procesos que se estén ejecutando es fundamental, en muchos casos, para el buen funcionamiento de los programas. El Sistema Operativo tiene que ofrecer servicios para que se pueda realizar esta comunicación de la forma más sencilla posible. En este punto, hay que dividir las comunicaciones entre procesos en dos tipos: aquellas que se realizan entre procesos que se ejecutan dentro de la misma computadora, y aquellas que se realizan entre procesos que están en distintas máquinas. Detección de errores. El sistema operativo debe estar constantemente pendiente de posibles errores, los cuales pueden darse en el hardware de la memoria y la CPU, en dispositivos de E/S o en un programa de usuario. Para cada tipo de error, el sistema operativo debe emprender la acción adecuada, para asegurar un funcionamiento correcto y consistente. Además, existe otro conjunto de funciones del sistema operativo, no para ayudar al usuario, sino para asegurar un funcionamiento eficiente del sistema. Los sistemas con varios usuarios pueden lograr mayor eficiencia compartiendo los recursos del computador entre los usuarios. • • • Asignación de recursos. Cuando varios usuarios o trabajos se ejecutan al mismo tiempo, se deben asignar recursos a cada uno de ellos. El Sistema Operativo administra los distintos tipos de recursos que existen en el sistema. Contabilidad. Deseamos llevar un control de qué usuarios utilizan qué recursos del computador. Estas anotaciones pueden tener fines contables (para facturar a los usuarios) o simplemente para recopilar estadísticas de uso, las cuales pueden ser una valiosa herramienta para los investigadores que desean reconfigurar el sistema a fin de mejorar los servicios. Protección. Posiblemente los dueños de la información almacenada en un sistema de computación multiusuario deseen controlar su uso. Cuando varios trabajos independientes se ejecutan al mismo tiempo, no debería ser posible que un trabajo interfiriera con los demás, ni con el sistema operativo. La protección implica revisar la validez de todos los parámetros que se pasan en las llamadas al sistema y asegurar que todo el acceso a los recursos del sistema esté controlado. También es importante la seguridad del sistema respecto a personas ajenas. Esta Curso: Sistemas Operativos Multiusuario. 6 Módulo 3: Estructura de los Sistemas Operativos. seguridad comienza con las contraseñas que los usuarios deben especificar para tener acceso a los recursos, y se extiende para defender a los dispositivos de E/S externos, incluyendo a los módems y adaptadores de red, de intentos de acceso no permitidos, y para registrar todas estas conexiones a fin de detectar intromisiones. Para que un sistema esté protegido y seguro, hay que establecer precauciones en todos los puntos vulnerables del sistema. 2. Llamadas al sistema. Las llamadas al sistema proporcionan la interfaz entre el Sistema Operativo y un programa en ejecución. Estas llamadas generalmente son instrucciones de lenguaje ensamblador. Algunos sistemas permiten efectuar llamadas al sistema directamente desde un programa realizado en lenguajes de mayor nivel, en cuyo caso las llamadas normalmente semejan llamadas a una función o subrutina predefinidas. Hoy en día, los lenguajes de programación de alto nivel, como pueden ser C, Java, Fortran,etc; sustituyen al lenguaje ensamblador en la programación de los sistemas, y permiten efectuar directamente llamadas al sistema. Un ejemplo de cómo se utilizan las llamadas al sistema podría ser un programa para leer datos de un archivo y copiarlos a otro. El programa necesitará primero los nombres de los dos archivos, el de entrada y el de salida, los cuales pueden especificarse de varias maneras, dependiendo del diseño del sistema operativo; un método es que el programa solicite al usuario los nombres de ambos archivos. En un sistema interactivo, esto requeriría una serie de llamadas al sistema, primero para escribir en la pantalla un mensaje de solicitud y luego para leer del teclado los caracteres que definen a los dos archivos. Otra forma, que se emplea con frecuencia en los sistemas por lotes, es especificar los nombres de los archivos mediante tarjetas de control. En este caso debe haber un mecanismo para pasar estos parámetros de las tarjetas al programa que se ejecuta. En los sistemas basados en ratón e iconos, generalmente en pantalla se presenta un menú con los nombres de los archivos. El usuario puede entonces usar el ratón para seleccionar el nombre del archivo fuente y abrir una ventana para especificar el nombre del archivo destino. Una vez que el programa ha obtenido los nombres de los dos archivos, debe abrir el archivo de entrada y crear el de salida; cada una de estas operaciones requiere otra llamada al sistema. También existen posibles condiciones de error para cada operación: cuando el programa trata de abrir el archivo de entrada, puede encontrar que no hay ningún archivo con ese nombre o que está protegido contra el acceso. En estas situaciones, el programa debe imprimir un mensaje en la consola (otra serie de llamadas al sistema) y luego terminar anormalmente (otra llamada al sistema). Si existe el archivo de entrada, entonces debemos crear un nuevo archivo de salida. Es posible encontrar que ya existe un archivo de salida con ese mismo nombre, situación que puede ocasionar que el programa aborte ( una llamada al sistema) o podemos eliminar el archivo existente (otra llamada al sistema) y crear uno nuevo (otra llamada al sistema). En un sistema interactivo, otra opción es preguntar al usuario (una serie de llamadas al sistema para presentar el mensaje de solicitud y leer la respuesta de la terminal) si se debe sustituir el archivo existente o abortar. Ahora que los dos archivos están listos, debemos entrar en el ciclo que lee del archivo de entrada (una llamada al sistema) y escribe en el de salida (otra llamada al sistema). Cada lectura y escritura debe devolver información de estado relacionada con las posibles condiciones de error. En la entrada, el programa puede encontrar que se ha alcanzado el fin del archivo o que durante la lectura se Curso: Sistemas Operativos Multiusuario. 7 Módulo 3: Estructura de los Sistemas Operativos. presentó un error de hardware (como puede ser un error de paridad). En la operación de escritura se puede encontrar varios errores, dependiendo del dispositivo de salida (espacio insuficiente en disco, fin de la cinta, impresora sin papel, etc). Finalmente, después de copiar todo el archivo, el programa puede cerrar ambos archivos (otra llamada al sistema), escribir un mensaje en la consola (más llamadas al sistema) y por fin terminar normalmente (la última llamada al sistema). Como podemos ver, los programas pueden hacer uso intensivo del sistema operativo. Todas las interacciones entre el programa y su entorno deben ocurrir como resultado de solicitudes del programa al sistema operativo. La mayoría de los usuarios jamás ve este nivel de detalle. El sistema de apoyo en tiempo de ejecución de la mayoría de los lenguajes ofrece una interfaz mucho más sencilla, que permite que el usuario no llegue a percatarse de las operaciones necesarias para realizar los pasos que se dan para realizar las operaciones que solicitan. De esta manera, el compilador y su paquete de apoyo en ejecución ocultan al usuario la mayor parte de los detalles de la interfaz con el sistema operativo. Las llamadas al sistema pueden efectuarse de varias maneras, dependiendo del computador. Las llamadas al sistema se clasifican normalmente en dos categorías generales: aquellas que se relacionan con procesos y la que lo hacen con el sistema de archivo. • Por Procesos: Un proceso es básicamente un programa en ejecución. Consta del programa ejecutable y la pila o stack del programa, su contador de programa, apuntador de pila y otros registros, así como la otra información que se necesita para ejecutar el programa. La ejecución de los procesos es parecida a como funcionan los sistemas operativos de tiempo compartido. Es decir, de manera periódica, el sistema operativo decide suspender la ejecución de un proceso y dar inicio a la ejecución de otro. Cuando un proceso se suspende temporalmente, debe reiniciarse después exactamente en el mismo estado en que se encontraba cuando se detuvo. Esto significa que toda la información relativa al proceso debe guardarse en forma explícita en algún lugar durante la suspensión. En muchos sistemas operativos, toda la información referente a cada proceso, se almacena en una tabla de sistema operativo llamada tabla de procesos, la cual es un arreglo (lista enlazada) de estructuras, una para cada proceso en existencia. Por lo tanto, un proceso en estado suspendido consta de su espacio de direcciones, generalmente denominado imagen del núcleo y su registro de la tabla de procesos, que contiene sus registros entre otras cosas. Todas las operaciones necesarias para el intercambio de procesos dentro de la CPU se producen mediante llamadas al Sistema Operativo. Es el Sistema Operativo el que controla el intercambio de procesos dentro de la CPU. • Por Sistema de Archivo: Una función importante del Sistema Operativo consiste en ocultar las peculiaridades de los discos y otros dispositivos de E/S y presentar al programador un modelo abstracto, limpio y agradable de archivos independientes del dispositivo. Las llamadas al sistema se utilizan para crear archivos, eliminarlos, leerlos y escribirlos. Curso: Sistemas Operativos Multiusuario. 8 Módulo 3: Estructura de los Sistemas Operativos. 3. Sistemas basados en interrupciones. En los Sistemas Operativos actuales, para poder superponer las operaciones de CPU y las de E/S, es necesario contar con mecanismos que permitan la sincronización de dichas operaciones. Puede usarse cualquiera de los métodos siguientes (o ambos): • • Transferencia de datos dirigida por interrupciones. Transferencia de datos por acceso directo a memoria (DMA, Direct Memory Access). En los Sistemas Operativos más antiguos, la transferencia de datos se efectuaba bajo el control de la CPU. La CPU, al tener que supervisar la transferencia de datos, no podía seguir ejecutando instrucciones de programas, sin permitir de esta manera superponer las operaciones simultáneas de CPU y de E/S. Como ejemplo, vamos a ver los pasos necesarios para imprimir una serie de datos que están en memoria: 1. 2. 3. 4. 5. Verificar si la impresora está lista para recibir el siguiente carácter. Si la impresora no está lista, volver al paso 1. Si la impresora está lista, verificar si hay otro carácter por imprimir. Si hay otro carácter, volver al paso 1. Si no hay más caracteres, la impresión ha terminado. A este método se conoce como espera activa, ya que la CPU necesita realizar un seguimiento del estado de la E/S y, por consiguiente, está activa mientras espera que termine la E/S. Aunque en teoría es cierto que la CPU podría efectuar algún otro procesamiento y regresar más tarde a imprimir el siguiente carácter, en la práctica esto no siempre es posible. Considere que aunque se emplea un dispositivo de entrada de alta velocidad, la CPU seguirá siendo más rápida, y por tanto, deberá esperar entre una y otra entrada. No obstante, si la CPU cambia a otra tarea para evitar esta pérdida de tiempo, se presenta el riesgo de omitir parte de la entrada, ya que durante ese lapso se pueden recibir dos entradas. La E/S basada en interrupciones se presenta como la mejor solución para esta situación. En un sistema basado en interrupciones, cada controlador de dispositivo se encarga de un tipo específico de dispositivo. Cada controlador cuenta con un buffer que le sirve de almacenamiento local y un conjunto de registros de carácter general. El controlador se encarga de traspasar los datos del dispositivo correspondiente, al buffer de datos. Para realizar una operación de E/S, la CPU modifica los valores de los registros del controlador para indicarle que debe de realizar una operación, por ejemplo de lectura de datos del dispositivo. A continuación, mientras la CPU continúa con su trabajo, el controlador analiza el valor de sus registros para saber qué operación debe de realizar. Al ver que es una operación de lectura, comienza a trasladar datos desde el dispositivo a su buffer local. Al terminar, el dispositivo tiene que informar a la CPU de que ha rematado la operación. Esta comunicación se produce mediante una interrupción. Cuando la CPU recibe la interrupción, suspende las operaciones que estaba haciendo y trasfiere el control a un pequeño programa, denominado rutina de procesamiento de interrupción. En este programa se encuentran las instrucciones que indican lo que se debe de hacer en caso de que se produzca dicha interrupción. La interrupción debe transferir el control a la rutina de procesamiento de la interrupción. Por lo general, esto se logra reservando un conjunto de Curso: Sistemas Operativos Multiusuario. 9 Módulo 3: Estructura de los Sistemas Operativos. posiciones en la parte baja de la memoria (aproximadamente las primera 100 posiciones) para que almacenen las direcciones de las rutinas de procesamiento de la interrupción para los distintos dispositivos. Este vector de direcciones se ordena usando un número de dispositivo único que se da junto con la solicitud de interrupción para así proporcionar la dirección de la rutina de procesamiento de la interrupción para el dispositivo que la emite. Las interrupciones son una parte importante de la arquitectura del computador. Cada diseño cuenta con su propio mecanismo de interrupción, pero hay varias funciones comunes. Cuando se produce la interrupción, la CPU suspende la ejecución de la instrucción que tenga en ese momento, la arquitectura de interrupciones también debe guardar la dirección de la instrucción interrumpida. En varios de los diseños más antiguos la dirección se almacenaba en una posición fija o en una posición marcada por el número de dispositivo. Las arquitecturas más recientes almacenan la dirección de retorno en la pila del sistema. Quizá la rutina de procesamiento de la interrupción tenga que guardar explícitamente otros registros, como acumuladores o registros de índices, y luego recuperarlos. Después de procesar la interrupción, con un salto a la dirección de retorno almacena, la ejecución continuará como si no hubiera ocurrido nada. Por regla general, cuando se está procesando una interrupción se desactivan el resto hasta que el Sistema Operativo termina de procesar la primera, momento en el cual se vuelven a activar las interrupciones. Si no se desactivaran, el procesamiento de la segunda interrupción mientras se da servicio a la anterior escribiría sobre los datos de la primera; y la primera sería una interrupción perdida. Las arquitecturas complejas de interrupciones permiten procesar una interrupción mientras se atiende otra, por lo general siguiendo un esquema donde se asignan prioridades a los tipos de solicitud de acuerdo con su importancia relativa, y se almacena por separado la información de procesamiento de la interrupción para cada prioridad. Se aceptará una interrupción de prioridad más alta aun si está activa una interrupción de menor prioridad, pero las interrupciones de igual o menor prioridad se enmascaran, o desactivan selectivamente, para evitar interrupciones perdidas o innecesarias. 4. Estructura de E/S. Si no hay trabajos que ejecutar, ni dispositivos de E/S a los cuales dar servicio, ni usuarios a quienes responder, el sistema operativo permanecerá inactivo esperando que algo suceda. Los sucesos casi siempre se avisan mediante una interrupción, o una trampa. Una trampa es una interrupción generada por el software a causa de un error, o de una solicitud específica de un programa de usuario para que se realice un servicio del sistema operativo. Una de las principales clases de sucesos que debe manejar un sistema operativo son las de interrupciones de E/S. Un dispositivo de E/S generará una interrupción al terminar una solicitud de E/S. Esta situación por lo general será cursada por un programa de usuario que solicite E/S. Una vez que la E/S se ha iniciado, es posible seguir dos tipos de acción. En el caso más simple, la E/S se inicia y al terminar, se devuelve el control al programa de usuario. La otra posibilidad es devolver el control al programa de usuario sin esperar que la E/S termine. Curso: Sistemas Operativos Multiusuario. 10 Módulo 3: Estructura de los Sistemas Operativos. La espera de la terminación de la E/S puede lograrse de dos maneras. Algunos computadores tienen una instrucción de espera especial que mantiene inactiva la CPU hasta la siguiente interrupción. Las máquinas que no poseen esta instrucción pueden tener un ciclo de espera: Ciclo: jmp Ciclo Se trata de un ciclo muy cerrado que continúa hasta que ocurre una interrupción, lo cual transfiere el control a otra parte del sistema operativo. La instrucción de espera es probablemente mejor, ya que un ciclo de espera genera una serie de búsquedas de instrucciones, lo que puede causar una contienda significativa por el acceso a memoria. La contienda es provocada por el dispositivo de E/S que transfiere información y la CPU que transfiere instrucciones. Una gran ventaja de esperar siempre a que termine la E/S es que como máximo hay una solicitud de E/S pendiente en cada ocasión, de manera que al ocurrir una interrupción de E/S, el sistema operativo sabe exactamente cuál es el dispositivo que interrumpe. Por otra parte, este método excluye al procesamiento de E/S. Una alternativa es comenzar la E/S y devolver de inmediato el control al programa de usuario. Se requiere entonces una llamada al sistema (una solicitud al sistema operativo) para permitir al usuario que espere la terminación de la E/S; por tanto, aún necesitamos el anterior código de espera, y también debemos llevar un control de varias solicitudes de E/S al mismo tiempo. Con este fin, el sistema operativo usa una tabla que contiene una entrada por cada dispositivo de E/S: la tabla de estado de dispositivos. Cada entrada de la tabla indica el tipo de dispositivo, así como su dirección y su estado (no funciona, inactivo u ocupado). Si el dispositivo está ocupado con una solicitud, el tipo de solicitud y otros parámetros se anotarán en la entrada de la tabla correspondiente al dispositivo. Puesto que es posible efectuar varias solicitudes para el mismo dispositivo, podemos tener una lista o cadena de solicitudes en espera. Así, además de la tabla de dispositivos de E/S, un sistema operativo puede contar con una lista de solicitudes para cada dispositivo. Un dispositivo de E/S interrumpe cuando requiere servicio. Dada esta situación, el sistema operativo primero determina cuál fue el dispositivo de E/S que causó la interrupción. Luego acude, usando un índice, a la tabla de dispositivos de E/S para determinar el estado del dispositivo y modificar la entrada de la tabla para reflejar la aparición de la interrupción. Para la mayoría de los dispositivos, una interrupción indica la terminación de una solicitud de E/S. Si está en espera alguna otra solicitud para ese dispositivo, el sistema operativo comienza a procesarla. Finalmente, se devuelve el control desde la interrupción de E/S. Si el programa estaba esperando a que terminara esta solicitud (según se anotó en la tabla de estado de dispositivos), ahora podemos devolverle el control. En caso contrario, regresamos a lo que estábamos haciendo antes de la interrupción de E/S: a la ejecución del programa de usuario (el programa inició una operación de E/S y ésta ya ha terminado, pero el programa todavía no ha solicitado esperar a que concluya la operación), o al ciclo de espera (el programa inició dos o más operaciones de E/S y está esperando a que termine una en particular, pero la interrupción corresponde a otra). Los esquemas utilizados por algunos dispositivos de entrada pueden variar respecto a éste. Muchos sistemas interactivos permiten a los usuarios teclear por adelantado, o introducir datos antes de que se les soliciten. En este caso pueden ocurrir interrupciones, indicando la llegada de caracteres de la terminal, mientras que el bloque de estado de dispositivos indica que ningún programa ha solicitado Curso: Sistemas Operativos Multiusuario. 11 Módulo 3: Estructura de los Sistemas Operativos. entradas de este dispositivo. Si se permite teclear por adelantado, entonces se debe proporcionar un buffer para almacenar los caracteres también por adelantado hasta que algún programa los quiera. En general, necesitaremos un buffer por cada terminal de entrada. 5. Operación de modo dual. A medida que los Sistemas Operativos evolucionaron, se fueron encargando del control de las distintas funciones que se pueden realizar en los sistemas de computación. En los primeros tiempos de la informática, eran los programadores los encargados de controlar totalmente todas las operaciones que realizaban las máquinas, pero los sistemas se han ido haciendo más y más complejos, y comenzó a ser necesario que la propia máquina fuese la encargada de controlar sus propias operaciones. Comenzando por el monitor residente, el Sistema Operativo comenzó a realizar varias funciones partiendo de las operaciones de E/S que antes eran responsabilidad de los programadores. Al mismo tiempo que los Sistemas Operativos evolucionaban e incluían nuevas mejoras y capacidades, los problemas y los riesgos de errores también aumentaron. Por poner un ejemplo, cuando el sistema funcionaba sin compartir recursos entre distintos programas, un error en uno de ellos, afectaba única y exclusivamente a dicho programa. Con la compartición, un error puede afectar a varios programas que se estén ejecutando en ese momento en el sistema, incluido el propio Sistema Operativo. Si los Sistemas Operativos no ofreciesen protecciones a ese tipo de errores, la ejecución de los trabajos debería de realizarse de uno en uno, con las innumerables desventajas que eso provoca. Un Sistema Operativo bien diseñado debe asegurar que un programa incorrecto no provoque la ejecución incorrecta de otros programas. El hardware de la computadora detecta muchos de los errores de programación que se pueden producir en el sistema: intentos de ejecución de instrucciones no permitidas, accesos a posiciones de memoria que no se corresponden con los espacios reservados para cada programa,... Cuando el hardware detecta un error de estos tipos, dirigirá una trampa al Sistema Operativo a través del vector de interrupciones. El Sistema Operativo, cuando se producen estas situaciones, hace que el programa termine de manera anormal, enviando los mensajes de error correspondientes. Este método funciona bien siempre que el hardware detecte el error. Sin embargo, debemos asegurarnos de que se detecten todos los errores y proteger al sistema operativo, así como a todos los demás programas y datos, de cualquier programa que no funcione correctamente. Se requiere protección para cualquier recurso compartido. La estrategia que se utiliza es proporcionar apoyo del hardware que permita distinguir entre diversos modos de ejecución. Por lo menos necesitamos dos modos de operación distintos: modo usuario y modo monitor (también llamado modo de supervisión o modo de sistema). Se añade un bit, llamado bit de modo, al hardware del computador para indicar el modo actual: monitor (0) o usuario (1). Con el bit de modo podemos distinguir entre una ejecución efectuada por el sistema operativo y una efectuada por el usuario. Al ocurrir una trampa o interrupción, el hardware cambia de modo usuario a modo monitor (es decir, cambia a 0 el estado del bit de modo). Así, cada vez que el sistema operativo obtiene el control del computador, se encuentra en modo Curso: Sistemas Operativos Multiusuario. 12 Módulo 3: Estructura de los Sistemas Operativos. monitor. El sistema siempre cambia a modo usuario antes de pasar el control a un programa de usuario. El modo dual de operación nos proporciona un medio para proteger al sistema operativo de los usuarios del sistema. Se consigue esta protección clasificando algunas de las instrucciones de la máquina que pueden causar daño como instrucciones privilegiadas. A las cuales el hardware permite ejecutarse sólo en modo monitor. Si se intenta ejecutar una instrucción privilegiada en modo usuario, el hardware no lo hace, sino que la considera como una instrucción incorrecta y dirige una trampa al sistema operativo. Si se carece de un modo dual apoyado por el hardware, se puede provocar serios defectos en un sistema operativo. 6. Estructura de los sistemas operativos. Un sistema tan complejo como un sistema operativo moderno debe construirse con cuidado para que funcione correctamente y pueda modificarse con facilidad. Un método común es dividir las tareas en fragmentos pequeños. Cada uno de estos fragmentos debe ser una porción bien definida del sistema, con entradas, salidas y funciones cuidadosamente especificadas. 6.1. Estructura sencilla. Varios de los Sistemas Operativos comerciales que se utilizan en la actualidad, no tienen una estructura bien definida. En muchos casos, estos Sistemas Operativos comenzaron como sistemas pequeños y limitados que crecieron más allá de su campo de aplicación original. Un ejemplo de éstos es MSDOS. MS – DOS fue diseñado e implantado originalmente por unas cuantas personas que no tenían la menor idea de la popularidad que lograría. Se escribió para ofrecer la mayor funcionalidad en el menor espacio, por lo que no se dividió cuidadosamente en módulos. Aunque MS – DOS cuenta con cierta estructura, sus interfaces y niveles de funcionalidad no están bien separados; por ejemplo, las aplicaciones pueden tener acceso a las rutinas básicas de E/S para escribir directamente en la pantalla y en las unidades de disco. Todas estas funcionalidades hacen que el sistema sea muy vulnerable a programas imperfectos. Por supuesto, MS – DOS también está limitado por el hardware en el que se ejecuta. Puesto que el procesador Intel 8088 para el cual se escribió no ofrece modo dual de operación ni protección de hardware, los diseñadores de MS – DOS no tuvieron más opción que dejar accesible el hardware base. Otro ejemplo de las limitaciones que existen en algunos de los sistemas operativos del mercado es el sistema operativo UNIX original, que inicialmente también estaba limitado por la funcionalidad del hardware. Consiste en dos partes separables: el núcleo y los programas de sistema. El núcleo se subdivide en una serie de interfaces y manejadores de dispositivos que se han ido agregando y ampliando al evolucionar UNIX, al que podemos ver como una serie de capas. Todo lo que se encuentra por debajo de la interfaz de llamadas al sistema y por encima del hardware físico es el núcleo. Éste proporciona, mediante llamadas al sistema, el sistema de archivos, la planificación de la CPU, la administración de memoria y otras funciones del sistema operativo. En conjunto, hay demasiadas funciones para organizarlas en un solo nivel. Los programas del sistema utilizan las llamadas al sistema proporcionadas por el núcleo para ofrecer funciones útiles, como la compilación y manipulación de archivos. Curso: Sistemas Operativos Multiusuario. 13 Módulo 3: Estructura de los Sistemas Operativos. Las llamadas al sistema definen la interfaz con el programador de UNIX; el conjunto de programas del sistema disponibles normalmente define la interfaz con el usuario. Las interfaces con el programador y el usuario definen el contexto que debe proporcionar el núcleo. Se han desarrollado varias versiones de UNIX donde el núcleo se divide aún más, haciendo divisiones funcionales. 6.2. Enfoque por capas. Las nuevas versiones de UNIX están diseñadas para utilizar un hardware más avanzado. Con el apoyo del hardware apropiado, los sistemas operativos se pueden dividir en fragmentos más pequeños y adecuados que los permitidos por las versiones originales de MS – DOS o UNIX. La nueva modularidad de los Sistemas Operativos permite un mayor control sobre la computadora y las aplicaciones que la utilizan; de la misma manera, los desarrolladores de sistemas tienen una mayor facilidad para realizar modificaciones sobre las partes internas del sistema: la división está mucho más clara y las modificaciones son más sencillas. Al usar el enfoque descendente pueden determinarse la funcionalidad y las características globales y separarlas en componentes, es decir, se parte de un concepto global del sistema y se va dividiendo en los distintos módulos que lo compondrán. Así mismo, es importante ocultar información, permitiendo a los programadores realizar las rutinas de bajo nivel que consideren adecuadas, siempre que la interfaz externa de la rutina permanezca sin cambios y la rutina lleve a cabo la tarea indicada. La modularización de un sistema puede lograrse de varias maneras, pero la más atractiva es el enfoque por capas, que consiste en dividir el Sistema Operativo en varias capas (niveles), cada una construida sobre las inferiores. La capa más baja (capa 0) es el hardware; la más alta (capa N) es la interfaz con el usuario. Una capa de sistema operativo es la implantación de un objeto abstracto que contiene datos y operaciones que pueden manipular esos datos. Una capa típica del sistema operativo, consiste en algunas estructuras de datos y un conjunto de rutinas que pueden ser invocadas por las capas de niveles superiores. A su vez, dicha capa, puede invocar operaciones de las capas inferiores. La principal ventaja del enfoque por capas es la modularidad. Las capas se seleccionan de manera que cada una utilice funciones (operaciones) y servicios únicamente de las capas inferiores. Con este enfoque es posible simplificar mucho la depuración y verificación del sistema. El primer nivel se puede depurar sin preocuparse por el resto del sistema, ya que, por definición, sólo utiliza el hardware básico para implementar sus funciones. Una vez depurado el primer nivel, puede suponerse su correcto funcionamiento mientras se trabaja con el segundo nivel, etc. Si durante la depuración de un nivel en particular se encuentra un error, sabemos que éste debe localizarse en ese nivel, ya que los niveles inferiores se han depurado. Por eso se simplifican el diseño y la implantación del sistema cuando éste se divide en capas. Cada capa se implanta utilizando únicamente las operaciones que proporcionan las capas inferiores. Una capa no necesita saber cómo se han implementado estas operaciones; sólo qué es lo que hacen. Por tanto, cada capa oculta la existencia de ciertas estructuras de datos, operaciones y hardware a los niveles superiores, es suficiente con que les proporcionen una interfaz indicando las operaciones que pueden utilizar. El enfoque por capas se empleó por primera vez en el sistema operativo THE en la Technische Hogeschool Eindhoven; THE se definió en seis capas. La capa más baja era el hardware; la siguiente implantaba la planificación de la CPU y la tercera Curso: Sistemas Operativos Multiusuario. 14 Módulo 3: Estructura de los Sistemas Operativos. capa implantaba la administración de memoria. El esquema de administración de memoria era memoria virtual. El nivel 3 contenía el manejador de la consola del operador. Puesto que el manejador de dispositivos, al igual que los buffers de E/S, se colocaba en el nivel 4, por encima de la administración de memoria, los buffers de E/S se encontraban también por encima de la consola del operador, de manera que las condiciones de error de E/S podían visualizarse en la consola del operador. La mayor dificultad con el enfoque por capas es definir los niveles en los que se va a definir el sistema: como una capa sólo puede utilizar las capas inferiores, es necesaria una buena planificación. El modelo de capas en el diseño de los Sistemas Operativos tiende en los últimos años a simplificarse, se diseñan menos capas pero con mayor funcionalidad, ofreciendo la mayoría de las ventajas del código modularizado a la vez que se evitan los difíciles problemas de la definición e interacción de las capas 7. Máquina virtuales. En teoría, un sistema de computación está formado por capas, y el hardware es el nivel más bajo en todos los sistemas. Por su parte, el núcleo, que se ejecuta en el nivel siguiente, utiliza las instrucciones del hardware para crear un conjunto de llamadas al sistema que emplean las capas superiores. Los programas del sistema que se encuentran por encima del núcleo son capaces de utilizar llamadas al sistema o instrucciones del hardware, y de algún modo estos programas no distinguen entre las dos. Por esto, aunque la manera de acceder a ellas sea diferente, ambas ofrecen cierta funcionalidad que el programa puede usar para crear funciones más avanzadas. Los programas del sistema, a su vez, tratan al hardware y a las llamadas al sistema como si se encontraran al mismo nivel. Algunos sistemas extienden este esquema aún más, permitiendo que los programas del sistema puedan llamarse fácilmente desde las aplicaciones. Como antes, aunque los programas del sistema se encuentran en un nivel superior al de las otras rutinas, las aplicaciones pueden considerar que todo se encuentra por debajo de ellas en la jerarquía, como si esas rutinas formaran parte de la misma máquina. Este enfoque por capas tiene su conclusión lógica en el concepto de máquina virtual. Al emplear técnicas de planificación de la CPU y la memoria virtual, un sistema operativo puede crear la ilusión de procesos múltiples que se ejecutan cada uno en su propio procesador con su propia memoria (virtual). Por supuesto, normalmente el proceso posee requisitos adicionales, como llamadas al sistema y un sistema de archivos que no ofrece el hardware por sí mismo. Por otra parte, el enfoque de máquina virtual no ofrece ninguna función adicional, pero sí una interfaz que es idéntica al hardware subyacente. A cada proceso se le otorga una copia (virtual) del computador subyacente. Los recursos del computador físico se comparten para crear las máquinas virtuales. Puede entonces planificarse la CPU para compartirla y aparentar que los usuarios cuentan con su propio procesador. Con la utilización de spoolers y un sistema de archivos se puede proporcionar lectores de tarjetas e impresoras de líneas virtuales. Una terminal normal de tiempo compartido ofrece al usuario la función de la consola del operador de la máquina virtual. Una de las mayores dificultades se refiere a los sistemas de disco. Suponga que la máquina física tiene tres manejadores de disco pero quiere dar servicio a siete máquinas virtuales; es obvio que no puede asignar una unidad de disco a cada una. Recuerde que el software de la máquina virtual necesitará un espacio Curso: Sistemas Operativos Multiusuario. 15 Módulo 3: Estructura de los Sistemas Operativos. considerable en disco para ofrecer memoria virtual y spoolers. La solución es proporcionar discos virtuales, idénticos en todos los aspectos excepto en el tamaño. El sistema implanta cada minidisco asignándole la cantidad de pistas que requiera en los discos físicos. Obviamente, la suma de los tamaños de los minidiscos debe ser menor que la cantidad de espacio disponible en el disco físico. De esta manera se proporciona a los usuarios su propia máquina virtual, y entonces pueden ejecutar cualesquiera de los paquetes de software disponibles en la máquina subyacente. Aunque el concepto de máquina virtual resulta útil, es difícil de implantar: se requiere mucho esfuerzo para proporcionar un duplicado exacto de la máquina subyacente. Recuerde, por ejemplo, que la máquina subyacente cuenta con dos modos: usuario y monitor. El software de la máquina virtual se puede ejecutar en modo monitor, puesto que es el sistema operativo. En sí, la máquina virtual sólo puede ejecutarse en modo usuario; sin embargo, así como la máquina física tiene dos modos, también debe poseerlos la máquina virtual. Por tanto, debemos contar con un modo usuario virtual y un modo monitor virtual, ambos ejecutándose en modo usuario físico. Aquellas acciones que provocan la transferencia de modo usuario a monitor en una máquina real (como una llamada al sistema o un intento de ejecutar una instrucción privilegiada) también deben provocar una transferencia de modo usuario virtual a modo monitor virtual en una máquina virtual. En general, es posible lograr fácilmente esta transferencia. Por ejemplo, cuando un programa que se ejecuta en modo usuario virtual en una máquina virtual efectúa una llamada al sistema, ocasionará una transferencia al monitor de la máquina virtual que existe en la máquina real. El modo usuario virtual es también un modo usuario físico. Cuando el monitor de la máquina virtual obtiene el control, puede cambiar el contenido de los registros y el contador de programa para que la máquina virtual simule el efecto de la llamada al sistema. Luego puede reiniciar la máquina virtual, observando que ahora se encuentra en modo monitor virtual. Si entonces la máquina virtual intenta, por ejemplo, leer del lector de tarjetas virtual, ejecutará una instrucción privilegiada de E/S. Puesto que la máquina virtual se ejecuta en modo usuario físico, esta instrucción activará una trampa al monitor de la máquina virtual y éste debe simular el efecto de la instrucción de E/S. Por supuesto, la principal diferencia es el tiempo; mientras que una E/S real podría ocupar 100 milisegundos, la E/S virtual podría requerir menos tiempo (por encontrarse en el spooler) o más (por ser interpretada). Además, la CPU se multiprograma entre varias máquinas virtuales, lo que las hace impredeciblemente más lentas; en un caso extremo, puede ser necesario simular todas las instrucciones para ofrecer una verdadera máquina virtual. El concepto de máquina virtual tiene varias ventajas. Observe que en este contexto se da una protección completa a los distintos recursos del sistema; cada máquina virtual está completamente aislada de las demás, por lo que no se presentan problemas de seguridad. Por otra parte, los recursos no se pueden compartir directamente; para compartirlos se han implantado dos estrategias: primero, es posible compartir un minidisco. Este esquema sigue el modelo de un disco físico compartido, pero se pone en práctica mediante software; con esta técnica los archivos se pueden compartir. En segundo término, se puede definir una red de máquinas virtuales y cada una puede enviar información a través de la red virtual de comunicaciones. Una vez más, la red tiene como modelo a la red física de comunicaciones, pero se implanta en software. Curso: Sistemas Operativos Multiusuario. 16 Módulo 3: Estructura de los Sistemas Operativos. Este sistema de máquina virtual es un vehículo perfecto para la investigación y desarrollo de sistemas operativos, pues por lo general es difícil cambiar un sistema operativo. Como son programas grandes y complejos, es difícil asegurar que un cambio en un punto no ocasione errores ocultos en alguna otra parte, situación que puede ser muy peligrosa por el poder del sistema operativo. Debido a que el sistema operativo se ejecuta en modo monitor, una modificación equivocada de un apuntador puede provocar un error que destruya todo el sistema de archivos; por eso es tan necesario probar cuidadosamente todas las modificaciones hechas al sistema operativo. Pero el sistema operativo se ejecuta en toda la máquina y la controla, por lo que hay que detener y dejar de usar el sistema mientras se efectúan y prueban los cambios. A este periodo comúnmente se le conoce como tiempo de desarrollo del sistema y, como los usuarios no pueden disponer del sistema, con frecuencia se programa para altas horas de la noche o para los fines de semana. Un sistema de máquina virtual puede eliminar gran parte de este problema. A los programadores del sistema se les proporciona su propia máquina virtual y el desarrollo se lleva a cabo en ella, no en una máquina física. Pocas veces hay que interrumpir el funcionamiento del sistema para su desarrollo. 8. Arquitectura general de sistemas El deseo de reducir el tiempo de preparación y mejorar la utilización del sistema de computación condujo al agrupamiento de trabajos en lotes, al almacenamiento temporal con spoolers y buffers, y finalmente a la multiprogramación y el tiempo compartido. Con estos enfoques se comparten los recursos del sistema de computación entre varios programas y trabajos diferentes. El comportamiento condujo directamente a modificaciones en la arquitectura básica de los computadores, para permitir que el sistema operativo mantuviera el control sobre el sistema de computación, y en especial sobre la E/S; este control es indispensable para proporcionar un funcionamiento continuado, consistente y correcto. Para mantener el control, los fabricantes introdujeron un modo dual de funcionamiento (modo usuario y modo monitor). Este esquema permite el concepto de instrucciones privilegiadas, sólo ejecutables en modo monitor. Las instrucciones de E/S y aquéllas para modificar los registros de administración de memoria o el cronómetro son instrucciones privilegiadas. Como se podrá imaginar, existen algunas otras instrucciones que se clasifican como privilegiadas. Por ejemplo, la instrucción halt (parada) es privilegiada; un programa de usuario nunca deberá ser capaz de detener al computador. También son privilegiadas las instrucciones para activar y desactivar el sistema de interrupciones, ya que el funcionamiento adecuado del cronómetro y la E/S depende de la capacidad de responder correctamente a las interrupciones. La instrucción para cambiar de modo usuario a modo monitor es privilegiada, y en muchas máquinas también lo es cualquier modificación del bit de modo. Dado que las instrucciones de E/S son privilegiadas, sólo las puede ejecutar el sistema operativo. Entonces, ¿cómo lleva a cabo la E/S un programa de usuario?. Al hacer privilegiadas las instrucciones de E/S, hemos evitado que los programas de usuario efectúen cualquier E/S, esté permitida o no. La solución a este problema es que, puesto que únicamente el monitor puede llevar a cabo la E/S, el usuario debe pedir al monitor que la efectúe en su nombre. Curso: Sistemas Operativos Multiusuario. 17 Módulo 3: Estructura de los Sistemas Operativos. La mayoría de los sistemas de computación modernos cuentan con un conjunto de instrucciones especiales denominadas llamadas al sistema (o llamada al monitor). Antes de contar con estas innovaciones, las llamadas al sistema se activaban cuando el programa de usuario ejecutaba un código de instrucción no definida, para el cual no se había determinado ninguna operación de hardware. Esto generaba una trampa de “instrucción ilegal” que daba como resultado una transferencia de control al monitor. Cuando se ejecuta una llamada al sistema, el hardware la trata como una interrupción. El control pasa a través del vector de interrupciones a una rutina de procesamiento del sistema operativo y el bit de modo se coloca en modo monitor. La rutina de procesamiento de la llamada al sistema forma parte del sistema operativo; el monitor examina la instrucción que provoca la interrupción para determinar que ha ocurrido una llamada al sistema. Un parámetro indica qué tipo de servicio requiere el programa de usuario, y la información adicional necesaria para la solicitud puede pasarse en registros o en memoria. El monitor ejecuta la solicitud y devuelve el control a la instrucción siguiente a la de llamada al sistema. Así, para realizar una operación de E/S, el programa de usuario ejecuta una llamada al sistema para solicitar que el sistema operativo lleve a cabo su operación de E/S. El sistema operativo, que se ejecuta en modo monitor, revisa la validez de la solicitud y, si lo es, realiza la E/S solicitada. El sistema operativo devuelve entonces el control al usuario. 9. Fundamentos de diseño e implementación del Sistema Operativo. 9.1. Fundamentos de Windows NT. Se puede decir que Windows NT representa la primera propuesta de la empresa Microsoft por construir un Sistema Operativo serio, capaz de competir con los Sistemas Operativos clásicos como UNIX o VMS. Para ello se ha elegido un enfoque cliente-servidor, con la intención de alcanzar el sueño de los Sistemas Distribuidos. 9.1.1. Diseño De Windows NT Windows NT presenta una arquitectura del tipo cliente-servidor. El Sistema Operativo ve a los programas de aplicación como si fueran clientes a los que hay que servir, para lo cual viene equipado con distintos servidores que realizan esas funciones. Uno de los objetivos fundamentales del diseño de Windows NT fue tener un núcleo tan pequeño como fuese posible. En el núcleo del sistema estarían integrados aquellos módulos que serían los encargados de responder a aquellas llamadas al sistema que necesariamente se tienen que ejecutar en modo privilegiado. Fuera del núcleo del Sistema Operativo, existen otras entidades que se encargan de responder al resto de llamadas que son expulsadas del núcleo y que son ejecutadas en modo no privilegiado. De esta manera, el núcleo resulta una base compacta, robusta y estable. Por eso se dice que Windows NT es un Sistema Operativo basado en microkernel. Curso: Sistemas Operativos Multiusuario. 18 Módulo 3: Estructura de los Sistemas Operativos. La arquitectura de Windows NT se basa en un núcleo que se ejecuta en modo privilegiado, que se denomina Executive, y unos módulos que se ejecutan en modo no privilegiado, llamadas subsistemas protegidos. Los programas de usuario interaccionan con cualquier Sistema Operativo a través de un juego de llamadas al sistema, que es particular de cada Sistema Operativo. En el mundo Windows en general, las llamadas al sistema se denominan API (Application Programming Interfaces, interfaces para la programación de aplicaciones). En Windows NT y en Windows 95 se usa una versión del API llamada API Win32. Un programa escrito para Windows NT o Windows 95, y que por consiguiente hace uso del API Win32, se denomina genéricamente "programa Win32", y de hecho esta denominación es bastante frecuente en artículos y libros al respecto. El término "Win32" tiene tres acepciones totalmente distintas. Una es el API, otra es el nombre de uno de los subsistemas protegidos de Windows NT del que se hablará más adelante, y por último se denomina Win32s a una plataforma desarrollada por Microsoft, similar a Windows 3.1, pero que usa el API Win32 en vez del API Win16 del Windows 3.1. Algunas de las llamadas al sistema, debido a su naturaleza, son atendidas directamente por el Executive, mientras que otras son desviadas hacia algún subsistema. El diseño de Windows NT, basado en núcleo y subsistemas, permite añadir nuevas partes al Sistema Operativo, es decir, nuevos subsistemas, sin producir ningún tipo de confrontación entre ellos. En el diseño de Windows NT han confluido aportaciones de tres modelos: el modelo cliente-servidor, el modelo de objetos, y el modelo de multiprocesamiento simétrico. • Modelo cliente-servidor. En la teoría de este modelo se establece un kernel que básicamente se encarga de recibir peticiones de procesos clientes y pasárselas a otros procesos servidores. Tanto los clientes como los servidores se están ejecutando en modo usuario. Windows NT pone el modelo en práctica pero no contempla el núcleo como un mero transportador de mensajes, sino que introduce en él aquellos servicios que sólo pueden ser ejecutados en modo kernel. El resto de servicios los asciende hacia subsistemas servidores que se ejecutan en modo usuario, independientes entre sí, y que por tanto pueden repartirse entre máquinas distintas, dando así soporte a un sistema distribuido (de hecho, el soportar los sistemas distribuidos fue otra de las grandes directivas de diseño de este SO). • Modelo de objetos. Decir que no implementa puramente la teoría de este modelo, sino que más bien lo que hace es simplemente contemplar los recursos (tanto internos como externos) como objetos. Hay que señalar que todo objeto ha de poseer identidad propia (es único y distinguible de todos los demás), y una serie de atributos (variables) y métodos (funciones) que modifican sus atributos. Los objetos interaccionan entre sí a través del envío de mensajes. No sólo existen en Windows NT objetos software (lógicos), sino que los dispositivos hardware (físicos) también son tratados como objetos. • Modelo de multiprocesamiento simétrico. Un SO multiproceso (o sea, aquel que cuenta con varias CPU y cada una puede estar ejecutando un proceso) puede ser simétrico (SMP) o asimétrico (ASMP). En los sistemas operativos SMP (entre los que se encuentran Windows NT y muchas versiones de UNIX) cualquier CPU puede ejecutar cualquier proceso, ya sea del SO o no, mientras que en los ASMP se elige una CPU para uso exclusivo del SO y el resto de las CPUs quedan para ejecutar programas de usuario. Los sistemas SMP son más Curso: Sistemas Operativos Multiusuario. 19 Módulo 3: Estructura de los Sistemas Operativos. complejos que los ASMP, contemplan un mejor balance de la carga y son más tolerantes a fallos (de manera que si un subproceso del SO falla, el SO no se caerá pues podrá ejecutarse sobre otra CPU, cosa que en los ASMP no sería posible, con lo que se bloquearía el sistema entero). Comencemos describiendo los subsistemas protegidos, para seguidamente estudiar la estructura del Executive. Figura. El núcleo se ejecuta en modo privilegiado (Executive) y en modo no privilegiado (subsistemas protegidos) 9.1.2. Los Subsistemas Protegidos Son una serie de procesos servidores que se ejecutan en modo usuario como cualquier proceso de usuario, pero que tienen algunas características propias que los hacen distintos. Se inician al arrancar el SO. Los hay de dos tipos: integrales y de entorno. Un Subsistema Integral: es aquel servidor que ejecuta una función crítica del SO (como por ejemplo el que gestiona la seguridad). Tenemos los siguientes: El Subsistema Proceso de Inicio (Logon Process) El proceso de inicio (Logon Process) recibe las peticiones de conexión por parte de los usuarios. En realidad son dos procesos que se encargan de gestionar los dos tipos de inicio de sesión que se pueden dar: • El proceso de inicio local: gestiona la conexión de usuarios locales directamente a una máquina Windows NT. • El proceso de inicio remoto: gestiona la conexión de usuarios remotos a procesos servidores de Windows NT. El Subsistema de Seguridad Curso: Sistemas Operativos Multiusuario. 20 Módulo 3: Estructura de los Sistemas Operativos. Este subsistema interacciona con el proceso de inicio y el llamado monitor de referencias de seguridad que forma parte del núcleo del sistema, construyendo el modelo de seguridad de Windows NT. El proceso de inicio y el subsistema de seguridad trabajan juntos. El subsistema de seguridad consta de dos subcomponentes: • La autoridad de seguridad local: es el corazón del subsistema. En general gestiona la política de seguridad local: se encarga de generar los permisos de acceso, de comprobar que el usuario que solicita conexión tiene acceso al sistema, de verificar todos los accesos sobre los objetos y de controlar la política de auditorías, llevando la cuenta de los mensajes de auditoría generados por el monitor de referencias. Las auditorías son una facilidad que proporciona Windows NT para monitorizar diversos acontecimientos del sistema por parte del Administrador. • El administrador de cuentas: mantiene una base de datos con las cuentas de todos los usuarios que tienen acceso al sistema(login, claves, identificaciones, etc.). Proporciona los servicios de validación de usuarios requeridos por el subcomponente anterior. Un Subsistema de Entorno Este subsistema da soporte a aplicaciones procedentes de SO distintos, adaptándolas para su ejecución bajo Windows NT. Existen tres de este tipo: El Subsistema Win32 Este subsistema es el encargado de atender, no sólo a aplicaciones nativas de Windows NT, sino también a aquellos programas que no son Win32. Para este tipo de aplicaciones, el subsistema reconoce su tipo y las lanza hacia el subsistema correspondiente. El subsistema soporta una buena parte del API Win32. Así, se encarga de todo lo relacionado con la interfaz gráfica con el usuario (GUI), controlando las entradas del usuario y salidas de la aplicación. El Subsistema POSIX La norma POSIX (Portable Operating System Interface for Unix) fue elaborada por IEEE para conseguir la portabilidad de las aplicaciones entre distintos entornos UNIX. La norma se ha implementado no sólo en muchas versiones de UNIX, sino también en otros Sistemas Operativos como Windows NT, VMS, etc. Se trata de un conjunto de 23 normas, identificadas como IEEE 1003.0 a IEEE 1003.22, o también POSIX.0 a POSIX.22, de las cuales el subsistema POSIX soporta la POSIX.1, que define un conjunto de llamadas al sistema en lenguaje C. El subsistema sirve las llamadas interaccionando con el Executive. Se encarga también de definir aspectos específicos del Sistema Operativo UNIX, como pueden ser las relaciones jerárquicas entre procesos padres e hijos (las cuales no existen en el subsistema Win32, por ejemplo, y que por consiguiente no aparecen implementadas directamente en el Executive). El Subsistema OS/2 Igual que el subsistema POSIX proporciona un entorno para aplicaciones UNIX, este subsistema da soporte a las aplicaciones OS/2. Proporciona la interfaz gráfica y las llamadas al sistema; las llamadas son servidas con ayuda del Executive. Curso: Sistemas Operativos Multiusuario. 21 Módulo 3: Estructura de los Sistemas Operativos. 9.1.3. El Executive No se debe confundir el Executive con el núcleo de Windows NT, aunque muchas veces se usan (incorrectamente) como sinónimos. El Executive consta de una serie de componentes software, que se ejecutan en modo privilegiado, y uno de los cuales es el núcleo. Dichos componentes son totalmente independientes entre sí, y se comunican a través de interfaces bien definidas. Recordemos que en el diseño se procuró dejar el núcleo tan pequeño como fuera posible, y, como veremos, la funcionalidad del núcleo es mínima. A continuación se verán los distintos módulos de los que se compone el Executive de Windows NT. El Administrador de Objetos (Object Manager) Se encarga de crear, destruir y gestionar todos los objetos del Executive. Tenemos infinidad de objetos: procesos, subprocesos, ficheros, segmentos de memoria compartida, semáforos, mutex, sucesos, etc. Los subsistemas de entorno (Win32, OS/2 y POSIX) también tienen sus propios objetos. El Administrador de Procesos (Process Manager) Se encarga (en colaboración con el administrador de objetos) de crear, destruir y gestionar los procesos y subprocesos. Una de sus funciones es la de repartir el tiempo de CPU entre los distintos subprocesos. Suministra sólo las relaciones más básicas entre procesos y subprocesos, dejando el resto de las interrelaciones entre ellos a cada subsistema protegido concreto. El Administrador de Memoria Virtual (Virtual Memory Manager) Windows NT y UNIX implementan un direccionamiento lineal de 32 bits y memoria virtual paginada bajo demanda se verán con más detalle en el siguiente módulo. El Administrador de Memoria Virtual se encarga de todo lo relacionado con la política de gestión de la memoria: determina los conjuntos de trabajo de cada proceso, mantiene un conjunto de páginas libres, elige páginas víctima, sube y baja páginas entre la memoria RAM y el archivo de intercambio en disco, etc. Facilidad de Llamada a Procedimiento Local (LPC Facility) Este módulo se encarga de recibir y enviar las llamadas a procedimiento local entre las aplicaciones cliente y los subsistemas servidores. Administrador de Entrada/Salida (I/O Manager) Consiste en una serie de subcomponentes, que son: • El administrador del sistema de ficheros • El servidor y el redirector de red • Los drivers de dispositivo del sistema El administrador de caches Buena parte de su trabajo es la gestión de la comunicación entre los distintos drivers de dispositivo, para lo cual implementa una interfaz bien definida que permite el tratamiento de todos los drivers de una manera homogénea, sin que intervenga el cómo funciona específicamente cada uno. Curso: Sistemas Operativos Multiusuario. 22 Módulo 3: Estructura de los Sistemas Operativos. Trabaja en conjunción con otros componentes del Executive, sobre todo con el Administrador de Memoria Virtual. Le proporciona la E/S síncrona y asíncrona, la E/S a archivos asignados en memoria y las caches de los ficheros. El administrador de caches no se limita a gestionar unos cuantos buffers de tamaño fijo para cada fichero abierto, sino que es capaz de estudiar las estadísticas sobre la carga del sistema y variar dinámicamente esos tamaños de acuerdo con la carga. El Núcleo (Kernel) Situado en el corazón de Windows NT, se trata de un micro-kernel que se encarga de las funciones más básicas de todo el Sistema Operativo: • Ejecución de subprocesos • Sincronización multiprocesador • Manejo de las interrupciones hardware • Nivel de Abstracción de Hardware (HAL) Es una capa de software incluida en el Executive que sirve de interfaz entre los distintos drivers de dispositivo y el resto del sistema operativo. Con HAL, los dispositivos se presentan al Sistema Operativo como un conjunto homogéneo, a través de un conjunto de funciones bien definidas. Estas funciones son llamadas tanto desde el Sistema Operativo como desde los propios drivers. Permite a los drivers de dispositivo adaptarse a distintas arquitecturas de E/S sin tener que ser modificados en gran medida. Además oculta los detalles hardware que conlleva el multiprocesamiento simétrico de los niveles superiores del Sistema Operativo. Llamadas a Procedimientos Locales y Remotos Windows NT, al tener una arquitectura cliente-servidor, implementa el mecanismo de llamada a procedimiento remoto (RPC) como medio de comunicación entre procesos clientes y servidores, situados ambos en máquinas distintas de la misma red. Para clientes y servidores dentro de la misma máquina, la RPC toma la forma de llamada a procedimiento local (LPC). RPC (Remote Procedure Call) Se puede decir que el sueño de los diseñadores de Windows NT es que algún día se convierta en un sistema distribuido puro, es decir, que cualquiera de sus componentes pueda residir en máquinas distintas, siendo el kernel en cada máquina el coordinador general de mensajes entre los distintos componentes. En la última versión de Windows NT esto no es aún posible. No obstante, el mecanismo de RPC permite a un proceso cliente acceder a una función situada en el espacio virtual de direcciones de otro proceso servidor situado en otra máquina de una manera totalmente transparente. LPC (Local Procedure Call) Las LPC se pueden considerar una versión de las RPC. Se usan cuando un proceso necesita los servicios de algún subsistema protegido, típicamente Win32. Curso: Sistemas Operativos Multiusuario. 23 Módulo 3: Estructura de los Sistemas Operativos. 9.1.4. Administración de Procesos El concepto de proceso que existe en Windows NT es distinto a los procesos de los Sistemas Operativos clásicos. En Windows, un proceso es una entidad no ejecutable que posee un espacio de direcciones propio y aislado, una serie de recursos y una serie de subprocesos. En el espacio de direcciones hay colocado algún código ejecutable (entre otras cosas). Bien, hemos dicho que un proceso es una entidad "no-ejecutable". En efecto, no puede ejecutar el código de su propio espacio de direcciones, sino que para esto le hace falta al menos un subproceso. Por consiguiente, un subproceso es la unidad de ejecución de código. Un subproceso está asociado con una serie de instrucciones, unos registros, una pila y una cola de entrada de mensajes (enviados por otros procesos o por el Sistema Operativo). Cuando se crea un proceso, automáticamente se crea un subproceso asociado llamado subproceso primario. Los subprocesos también se llaman "hebras de ejecución". Debe quedarnos muy claro, pues, que lo que se ejecutan son subprocesos, no procesos. Los procesos son como el soporte sobre el que corren los subprocesos. Y entre los subprocesos se reparte el tiempo de CPU. Podemos pensar en los subprocesos de Windows NT como los procesos de los Sistemas Operativos clásicos aunque existen matices. Un proceso tiene un espacio de direcciones virtuales. En algún lugar de ese espacio se halla un código ejecutable. Un proceso puede crear subprocesos, estando su número fijado por el sistema. Un proceso se dice que muere cuando todos sus subprocesos han muerto incluso aunque el subproceso primario haya muerto, si aún existe algún subproceso propiedad del proceso, el proceso seguirá vivo. 9.1.4.1. Planificación del Tiempo de la CPU por Round Robin con Prioridades Aunque los aspectos referidos a como se realiza la planificación de la CPU se verán con mayor detenimiento en el siguiente módulo, se introducirá en este momento como se realiza dicha planificación en los sistemas Windows NT. Windows NT utiliza la planificación del anillo circular o round robin. Esta técnica consiste en que los subprocesos que pueden ser ejecutados se organizan formando un anillo, y la CPU va dedicándose a cada uno durante un tiempo. El tiempo máximo que la CPU va a estar dedicada a cada uno se denomina quantum, y es fijado por el Administrador del Sistema. Si el subproceso está esperando por alguna entrada-salida o por algún suceso, la CPU lo pondrá a dormir, y pondrá en ejecución al siguiente del anillo. Si un subproceso que la CPU está ejecutando consume su quantum, la CPU también lo pondrá a dormir, pasando al siguiente. En Windows NT, existe un rango de prioridades que va del 1 al 31, siendo 31 la más alta. Todo proceso y subproceso tienen un valor de prioridad asociado. Existe un anillo o cola circular por cada uno de los niveles de prioridad. En cada anillo están los subprocesos de la misma prioridad. El Executive comienza a repartir el tiempo de CPU en el primer anillo de mayor prioridad no vacío. A cada uno de esos subprocesos se les asigna secuencialmente la CPU durante el tiempo de un quantum, como ya indicamos antes. Cuando todos los subprocesos de nivel de prioridad n están dormidos, el Executive comienza a ejecutar los del nivel (n-1), siguiendo el mismo mecanismo. Curso: Sistemas Operativos Multiusuario. 24 Módulo 3: Estructura de los Sistemas Operativos. Análogamente, si un subproceso se está ejecutando, y llegara uno nuevo de prioridad superior, el Executive suspendería al primero (aunque no haya agotado su quantum), y comenzaría a ejecutar el segundo (asignándole un quantum completo). 9.1.4.2. Prioridad de proceso y subproceso Un proceso se dice que pertenece a una clase de prioridad. Existen cuatro clases de prioridad, que son: • Desocupado. Corresponde a un valor de prioridad 4. • Normal. Corresponde a un valor de prioridad 7 ó 9. • Alta. Corresponde a un valor de prioridad 13. • Tiempo Real. Corresponde a un valor de prioridad 24. La clase "Normal" es la que el Executive asocia a los procesos por defecto. Los procesos en esta clase se dice que tienen una prioridad dinámica: el Executive les asigna un valor de 7 si se están ejecutando en segundo plano, mientras que si pasan a primer plano, la prioridad se les aumenta a un valor de 9. La clase "Desocupado" va bien para procesos que se ejecuten periódicamente y que por ejemplo realicen alguna función de monitorización. La clase "Alta" la tienen procesos tales como el Administrador de Tareas (Task Manager). Dicho proceso está la mayor parte del tiempo durmiendo, y sólo se activa si el usuario lo desea. Entonces, el Sistema Operativo inmediatamente pone a dormir al subproceso en ejecución (aunque no haya agotado su quantum) y ejecuta el subproceso correspondiente al proceso Administrador de Tareas, que visualizará el cuadro de diálogo característico, mostrándonos las tareas actuales. La clase "Tiempo Real" no es recomendable que la tenga ningún proceso normal. Es una prioridad más alta incluso que muchos procesos del sistema, como los que controlan el ratón, el teclado, el almacenamiento en disco en segundo plano, etc. Es evidente que usar esta prioridad sin un control extremo puede causar consecuencias nefastas. Así como un proceso tiene una prioridad oscilando entre cuatro clases, un subproceso puede tener cualquier valor en el rango [1,31]. En principio, cuando el subproceso es creado, su prioridad es la correspondiente a la de la clase de su proceso padre. Pero este valor puede ser modificado. 9.1.5. Administración De La Memoria La parte de Windows NT que soporta la gestión de la memoria se denomina Gestor de Máquina Virtual (VMM), y reside en el Executive, por encima del núcleo pero ejecutándose en modo supervisor. En Windows NT se utiliza memoria virtual paginada. En algunas máquinas, como las CPU Intel 386 en adelante, combina paginación con segmentación. El tamaño de la página depende de la máquina. En la CPU anterior es de 4 Kb. Curso: Sistemas Operativos Multiusuario. 25 Módulo 3: Estructura de los Sistemas Operativos. 9.1.5.1. Espacio de Direcciones de un Proceso Todo proceso que se crea en Windows NT posee un espacio de direcciones virtuales de 4 Gb exclusivos de él. Ningún otro podrá acceder a esas direcciones, sencillamente porque ¡no las ve!. Para un proceso, todo lo que ve es suyo, y ve virtualmente 4 Gb. Los 2 Gb superiores están reservados al Sistema Operativo, así como los 64 Kb primeros y los 64 Kb últimos de los 2 Gb inferiores. El resto de los 2 Gb inferiores son para uso del proceso. Distinguimos varias zonas: • Direcciones para las DLL del sistema (NTDLL, KERNEL32, USER32, GDI32 ...). • Direcciones para las DLL propias de la aplicación. • Bloques y pilas de los subprocesos. • Imagen del archivo ejecutable: código, datos, cabecera, información del depurador y tabla de activación imagen. Además, cada proceso posee una tabla de implantación de páginas (TIP). El objetivo de esa tabla (también llamada tabla de traducción) es, dada una dirección virtual, devolver su dirección física asociada. A veces la dirección virtual no tiene correspondencia en memoria física. Entonces se dice que se ha producido un fallo o defecto de página (page fault). En el siguiente apartado vamos a describir cómo funciona el VMM y qué hace cuando se dan los fallos de página. 9.1.5.2. Funcionamiento del VMM Cada proceso tiene asignado un número que indica el máximo de páginas físicas que se le pueden conceder. Dicho número es ajustado por el llamado gestor del conjunto de trabajo. Además, cada proceso lleva asociada una lista que contiene referencias a las páginas físicas a las que se ha accedido menos últimamente. Cuando el proceso accede a una dirección que no tiene dirección física asociada en la TIP, se produce un fallo de página. Entonces, el VMM consulta el número de páginas que el proceso tiene asignadas. Si no ha llegado al límite, se le concede una nueva página física y se escribe con la correspondiente desde el disco. Esto se denomina paginación bajo demanda. Si por el contrario ya había llegado al límite, entonces hay que descargar una página física al disco para subir a memoria la que ocasionó el fallo. El VMM elige la página víctima de la lista de menos recientemente usadas del proceso. Hay que tener en cuenta que aunque existan páginas libres en la memoria, si el proceso agota su número de páginas asignadas, se producirá el intercambio de páginas (swapping), y además de una de sus propias páginas. Este mecanismo puede parecer ilógico, pero presenta tanto ventajas como inconvenientes. Una de los principales problemas es que si un proceso estuviera gran parte del tiempo dormido (en espera de un suceso o de una E/S), dicho proceso estaría ocupando páginas físicas que de otro modo podrían ser descargadas. Como ventaja tenemos que, con este esquema, procesos que requieran muchos recursos no dejarán fuera de juego a aquellos cuya demanda de memoria sea escasa. No obstante, el problema planteado es paliado en gran medida por una parte del VMM llamada gestor del conjunto de trabajo. Realiza dos funciones fundamentales: • Por un lado, periódicamente revisa las estadísticas sobre el uso de la CPU por cada proceso. Siguiendo este criterio, procede a ajustar el número que indica el máximo de páginas físicas asociadas a cada uno. A aquellos procesos con poca actividad se les reducirá el número (lo que acarreará un Curso: Sistemas Operativos Multiusuario. 26 Módulo 3: Estructura de los Sistemas Operativos. descargue de sus páginas físicas, si las tiene, cuando sean necesarias), y a aquellos con mucha carga se les aumentará el número. • Por otro lado, y también de forma periódica, roba a los procesos páginas físicas, elegidas de entre las menos recientemente usadas por cada uno. Este procedimiento se realiza con la frecuencia necesaria para que los procesos no se ralenticen demasiado por los fallos de página. El objetivo de esto es mantener una reserva de páginas para que una repentina demanda no ocasione una caída en prestaciones del sistema completo. Por ejemplo, cuando se inicia un proceso nuevo se suele requerir una cantidad considerable de páginas. Para llevar a cabo estas tareas, las páginas físicas se clasifican en una de cuatro listas que son mantenidos por el gestor del conjunto de trabajo: o lista de páginas modificadas o lista de páginas no activas o lista de páginas liberadas o lista de páginas a cero Cada página que el gestor roba a un proceso es borrada de la lista de menos recientemente usadas e incluida en la lista de modificadas (y las entradas correspondientes de la TIP marcadas como no válidas, de forma que se produzca fallo de página al acceder el proceso a dichas direcciones). Dicha lista contiene páginas robadas que aún están en memoria RAM pero que no han sido escritas a disco (al archivo de paginación). Cuando se produzca un fallo de página, si la dirección física correspondiente estuviera en una de estas páginas, simplemente se volvería a insertar en la lista del proceso y se ajustaría su TIP. Cuando la lista de modificadas se hace suficientemente grande, otra parte del VMM (el escritor de páginas) copia algunas páginas de la lista al archivo de paginación, las borra de la lista de modificadas y las añade a la lista de inactivas. Ahí están las páginas que han sido robadas, que están en RAM y además en el archivo de paginación. El tratamiento de un fallo de página aquí también sería muy rápido y simple. Cuando un proceso libera memoria, sus páginas físicas asociadas se añaden a la lista de liberadas. Son, por tanto, potencialmente utilizables sin necesidad de escribirlas en el fichero de swapping pero su contenido no ha sido borrado (están tal y como las dejó el proceso propietario). Periódicamente, estas páginas van siendo inicializadas con ceros,y añadidas a la lista de páginas a cero. El mecanismo de inicialización es para proteger la intimidad del antiguo proceso propietario. Cualquier página que se entrega a un proceso ha de haber sido convenientemente inicializada. Cuando un proceso requiere memoria física, el Administrador de Memoria Virtual comienza cogiendo páginas de la lista de inicializadas. Cuando está vacía, toma de la lista de liberadas, y las inicializa. Cuando ésta se vacía, toma de la lista de inactivas, y las inicializa. Sólo como última opción recurre a las modificadas. Estas últimas requieren escritura en el archivo de paginación junto con inicialización, lo cual es un proceso lento. En ambientes en los que la memoria es escasa, el gestor del conjunto de trabajo se centra en mantener un conjunto aceptable de páginas disponibles, más que en revisar las estadísticas de uso de la CPU. Curso: Sistemas Operativos Multiusuario. 27 Módulo 3: Estructura de los Sistemas Operativos. Como valores aproximativos, podemos señalar que si el número de páginas a cero más las liberadas más las inactivas suman menos de 20, el gestor robará páginas a procesos que comparten la CPU. Si el número de modificadas supera las 30, procederá a descargar algunas a disco, pasándolas a inactivas. 9.1.5.3. Archivos Asignados en Memoria Estudiemos ahora cómo el SO utiliza esta facilidad para cargar el código de un ejecutable y sus bibliotecas DLL asociadas. Un archivo asignado en memoria es todo aquel archivo para el que se ha reservado una región del espacio de direcciones virtuales de un proceso. Puede estar asignado el archivo completo o sólo una porción del mismo. Al principio, el VMM no asigna ninguna página física para el archivo asignado en memoria. El proceso simplemente supone que en ciertas direcciones de su espacio tiene cargado el fichero, así que cuando acceda a alguna se producirá un fallo de página. Es entonces cuando el VMM le asigna algunas páginas físicas y las copia desde el disco (paginación bajo demanda). La gestión del VMM de los archivos asignados en memoria es como cualquier otra región del espacio direccionable del proceso, excepto que el swapping se hace directamente sobre el archivo, en este caso el archivo de intercambio es el propio archivo asignado en memoria). Cuando se arranca un proceso con su código grabado en un fichero, el VMM asigna automáticamente dicho fichero en el espacio de direcciones del proceso. También asigna todas las bibliotecas incluidas explícitamente y todas aquellas a las que se hace referencia en el código. Dentro del ejecutable existe una tabla llamada tabla de activación imagen cuyas entradas contienen las funciones de biblioteca que se llaman durante el código. Una vez que se cargan las DLL (bibliotecas) en el espacio, el VMM completa la tabla escribiendo para cada entrada la dirección que ocupa la correspondiente función en el espacio del proceso. Por tanto, cada llamada a función implica una búsqueda en la tabla. 9.1.6. Sistema De Archivos Windows NT soporta cuatro tipos de sistemas de ficheros distintos, y puede trabajar con los cuatro a la vez (un disco con varias particiones, en cada una un Sistema de ficheros distinto). Son los siguientes: Sistema de Archivos Sistemas Operativos Soportados FAT DOS, Windows NT, y OS/2 PSF OS/2 y Windows NT NTFS Windows NT CDFS Windows NT Curso: Sistemas Operativos Multiusuario. 28 Módulo 3: Estructura de los Sistemas Operativos. NTFS (New-Technology File System): Es el sistema de ficheros nativo de Windows-NT. Como características podemos señalar: • Permite nombres de archivo de hasta 255 caracteres, sensibles al tipo de letra. • Permite la gestión de medios de almacenamiento extraordinariamente grandes. • Incorpora mecanismos para garantizar la seguridad. • Soporta el concepto de enlace (por compatibilidad con el estándar POSIX). • Es capaz de recomponerse rápidamente después de una caída del sistema. • Soporta el estándar Unicode. El que usa MS-DOS y Windows 16 bits. Es el Sistema de ficheros más pobre, y se mantiene para dar soporte a las aplicaciones DOS. HPFS (High-Performance File System): Es el que usa el sistema operativo OS/2. Se ha incluido para dar soporte a las aplicaciones OS/2 y complementar así al subsistema del mismo nombre. No es capaz de recomponerse del todo bien después de una caída del sistema ni de asegurar la no corrupción de los datos. CDFS (CD-ROM File System): Es un Sistema de ficherosF que Microsoft ha desarrollado exclusivamente para montarse sobre los CD-ROM. Sistema de ficheros NTFS Este sistema de ficheros lleva incorporados muchos conceptos de teoría de bases de datos relacionales. Proporciona la seguridad, recuperación y tolerancia a fallos en base a la redundancia de datos. De hecho, implementa los cinco primeros niveles del pseudoestándar RAID. RAID significa Redundant Arrays of Inexpensive Disks, algo así como "vectores redundantes de discos baratos". Actualmente, el coste de los almacenamientos masivos o secundarios es muy pequeño. RAID es una "norma" que se basa fundamentalmente en conseguir la integridad de los datos a base de dividirlos en pedazos y repartir los pedazos entre varios discos, junto con informaciones redundantes de comprobación de errores. Cada nivel ofrece una estrategia distinta para conseguir la integridad. Los niveles son: • Nivel 0: los datos de cada fichero se dividen en porciones, las cuales se reparten en un orden fijo entre los distintos discos con los que cuente el sistema. Realmente aquí no se usan códigos de comprobación de errores. • Nivel 1: de cada disco se realiza una copia o espejo. Es la estrategia que da mayor fiabilidad (pero también, evidentemente, la más costosa). • Nivel 2: como el 0, pero un algoritmo va construyendo una serie de códigos correctores de errores. Esos códigos son igualmente distribuidos entre unos discos destinados especialmente a ese uso. • Nivel 3: como el 2, pero no se usan códigos correctores sino un simple código de paridad, que puede ser guardado en un mismo disco para todos los ficheros. Curso: Sistemas Operativos Multiusuario. 29 Módulo 3: Estructura de los Sistemas Operativos. • Nivel 4: como el 3, pero dividiendo los ficheros en segmentos de datos más grandes. • Nivel 5: es el nivel más usual; es igual que el4, pero no usa un disco separado para almacenar los códigos de paridad, sino que divide igualmente esos códigos y los distribuye por los disco, intentando que no coincidan en la misma zona de disco datos de un fichero con sus códigos de paridad correspondientes. • Nivel 6: igual que el 5 pero se auxilia de elementos hardware, tales como controladoras de disco especiales, fuentes de alimentación. En NTFS, al igual que en los Sistemas de ficheros de UNIX, existen una serie de permisos sobre ficheros y directorios, que son los siguientes: lectura (R), escritura (W), ejecución (X), borrado (D), cambio de permisos (P) y ser el nuevo propietario (O). Todo fichero y directorio tienen un propietario, que puede conceder permisos sobre ellos. El Administrador del sistema puede tomar la propiedad de cualquier fichero o directorio sobre NTFS, pero no transferirla de nuevo a ningún otro usuario, a diferencia de UNIX, ni siquiera a su dueño original. Sistemas de Ventajas Archivos Desventajas FAT El rendimiento decrece con Poco consumo de sistema. El mejor particiones de más 200MB. No para discos y/o particiones de menos se pueden aplicar permisos de 200MB. sobre archivos y directorios. HPFS El mejor para discos y/o particiones entre 200 y 400 MB. Elimina la fragmentación almacenando en un solo bloque el archivo completo. NTFS El mejor para volúmenes de 400MB o recomendable para más. Recuperable (registro de No de menos de transacciones), diseñado para no volúmenes ejecutarle utilerias de reparación. Es 400MB. Consume de 1 a 5 MB posible establecer permisos y registro de acuerdo al tamaño de la de auditoría sobre archivos y partición. directorios. No es eficiente para menos de 200MB.No soporta hot fixing. No se pueden aplicar permisos sobre archivos y directorios. 9.1.7. Entrada/Salida El Manejador de E/S es la parte de Windows NT ejecutivo que maneja todas las entradas y todas las salidas del S.O.. Gran parte del rol de este Manejador es manejar las comunicaciones entre drivers. El Manejador de E/S soporta todos los sistemas de archivos de drivers, manejadores de dispositivos de hardware y manejadores de redes y provee un ambiente heterogéneo para ellos. Provee una interface formal que todos los manejadores o drivers pueden invocar. Esta interface uniforme le permite al Manejador de E/S comunicarse con todos los drivers de la Curso: Sistemas Operativos Multiusuario. 30 Módulo 3: Estructura de los Sistemas Operativos. misma manera sin tener conocimiento de cual de los dispositivos esta controlando actualmente. El Manejador de E/S también incluye rutinas especiales designadas para soporte de manejadores de sistemas de archivo, de dispositivos de hardware y de dispositivos de red. El modelo de Windows NT para E/S usa una arquitectura de niveles que permite manejadores separados para implementar cada capa lógica distinta de un procesamiento de E/S. Manejador de cache La arquitectura de E/S incluye un único Manejador de cache que maneja la totalidad de las E/S del sistema por este método. El Manejador de cache provee sus servicios a todos los archivos de sistema y componentes de red bajo el control del Manejador de E/S. El Manejador de cache puede hacer crecer dinámicamente y disminuir el tamaño de la memoria cache a medida que varia la cantidad de memoria RAM disponible. Cuando un proceso abre un archivo que ya reside en la memoria cache, el Manejador de cache simplemente copia los datos de la cache al espacio de direcciones virtual del proceso y viceversa; la lectura y la grabación mejoran. Sistemas de manejo de archivos En la arquitectura Windows NT de E/S, los manejadores de sistema de archivos son dirigidos por el Manejador de E/S. Windows NT soporta múltiples sistemas de archivos activos, incluyendo sistemas de archivos existentes como la F.A.T. Windows NT soporta sistemas de archivos F.A.T. y HPFS para resguardar la compatibilidad con los sistemas operativos MS-DOS, Windows 3.X y OS/2. La arquitectura de Windows NT de E/S no solamente soporta sistemas de archivos tradicionales sino que ha implementados su redirector de redes y servidor como un sistema de manejadores de archivos. Desde la perspectiva del Manejador de E/S no hay diferencia entre acceder archivos almacenados en una computadora remota vía red y acceder a aquellos almacenados localmente en un disco rígido. Además los redirectores y servidores pueden cargarse y descargarse dinámicamente como cualquier otro Manejador, y pueden coexistir múltiples redirectores y servidores a la misma computadora. Manejadores de dispositivos de hardware Los manejadores de dispositivos de hardware también son componentes de la arquitectura de la E/S. Todos ellos (como manejadores de impresión, de Mouse, de disco) están escritos en el lenguaje de programación C. Los manejadores de dispositivos acceden a los registros hardware de los dispositivos periféricos a través de rutinas de soporte que provee el sistema operativo Windows NT. Hay un conjunto de estas rutinas para cada plataforma que soporta Windows NT. Como los nombres de las rutinas son iguales para todas las plataformas los manejadores de dispositivos para Windows NT son transportable entre cualquier tipo de procesadores. Manejadores de red Un tercer tipo de Manejador implementado como un componente de la arquitectura de E/S es el Manejador de red. Windows NT incluye capacidades de funcionamiento de red integradas y soporte para aplicaciones distribuidas. Curso: Sistemas Operativos Multiusuario. 31 Módulo 3: Estructura de los Sistemas Operativos. 9.2. SISTEMA OPERATIVO UNIX 9.2.1. Características Generales: El Sistema Operativo UNIX posee las siguientes características: - Es un Sistema Operativo multiusuario, con multiprocesamiento y procesamiento no interactivo. capacidad de simular - Está escrito en un lenguaje de alto nivel: C. - Dispone de un lenguaje de control programable llamado SHELL. - Ofrece facilidades para la creación de programas y sistemas y el ambiente adecuado para las tareas de diseños de software. - Emplea manejo dinámico de memoria por intercambio o paginación. - Tiene capacidad de interconexión de procesos. - Permite comunicación entre procesos. - Emplea un sistema jerárquico de archivos, con facilidades de protección de archivos, cuentas y procesos. - Tiene facilidad para redireccionamiento de Entradas/Salidas. - Garantiza un alto grado de portabilidad. El sistema se basa en un Núcleo llamado Kernel, que reside permanentemente en la memoria, y que atiende a todas las llamadas del sistema, administra el acceso a los archivos y el inicio o la suspención de las tareas de los usuarios. La comunicación con el sistema UNIX se da mediante un programa de control llamado SHELL. Este es un lenguaje de control, un intérprete, y un lenguaje de programación, cuyas características lo hacen sumamente flexible para las tareas de un centro de cómputo. Como lenguaje de programación abarca los siguientes aspectos: - Ofrece las estructuras de control normales: secuenciación, iteración condicional, selección y otras. - Paso de parámetros. - Sustitución textual de variables y Cadenas. - Comunicación bidireccional entre órdenes de shell. El shell permite modificar en forma dinámica las características con que se ejecutan los programas en UNIX: Curso: Sistemas Operativos Multiusuario. 32 Módulo 3: Estructura de los Sistemas Operativos. • Las entradas y salidas pueden ser redireccionadas o redirigidas hacia archivos, procesos y dispositivos; • Es posible interconectar procesos entre sí. • Diferentes usuarios pueden "ver" versiones distintas del sistema operativo debido a la capacidad del shell para configurar diversos ambientes de ejecución. Por ejemplo, se puede hacer que un usuario entre directamente a su sección, ejecute un programa en particular y salga automáticamente del sistema al terminar de usarlo. 9.2.2. El núcleo del Sistema Operativo El núcleo del Sistema Operativo Unix (llamado Kernel) es un programa escrito casi en su totalidad en lenguaje C, con excepción de una parte del manejo de interrupciones, expresada en el lenguaje ensamblador del procesador en el que opera. Las funciones del núcleo son permitir la existencia de un ambiente en el que sea posible atender a varios usuarios y múltiples tareas en forma concurrente, repartiendo al procesador entre todos ellos, e intentando mantener en grado óptimo la atención individual de cada uno de los procesos. El Kernel opera como asignador de recursos para cualquier proceso que necesite hacer uso de las facilidades de cómputo. Es el componente central de Unix y tiene las siguientes funciones: - Creación de procesos, asignación de tiempos de atención y sincronización. - Asignación de la atención del procesador a los procesos que lo requieren. - Administración de espacio en el sistema de archivos, que incluye: acceso, protección y administración de usuarios; comunicación entre usuarios v entre procesos, y manipulación de E/S y administración de periféricos. Curso: Sistemas Operativos Multiusuario. 33 Módulo 3: Estructura de los Sistemas Operativos. - Supervisión de la transmisión de datos entre la memoria principal y los dispositivos periféricos. El Kernel reside siempre en la memoria central y tiene el control sobre la computadora, por lo que ningún otro proceso puede interrumpirlo; sólo pueden llamarlo para que proporcione algún servicio de los ya mencionados. Un proceso llama al Kernel mediante las llamadas al sistema. El Kernel consta de dos partes principales: la sección de control de procesos y la de control de dispositivos. La primera asigna recursos, programas, procesos y atiende sus requerimientos de servicio; la segunda, supervisa la transferencia de datos entre la memoria principal y los dispositivos periféricos. En términos generales, cada vez que algún usuario oprime una tecla de una terminal, o que se debe leer o escribir información del disco magnético, el núcleo se encarga de efectuar la operación de transferencia. Cuando se enciende un ordenador, debe cargarse en la memoria una copia del núcleo, que reside en el disco magnético (operación denominada bootstrap). Para ello, se deben inicializar algunas interfaces básicas de hardware; entre ellas, el reloj que proporciona interrupciones periódicas. El Kernel también prepara algunas estructuras de datos que abarcan una sección de almacenamiento temporal para Curso: Sistemas Operativos Multiusuario. 34 Módulo 3: Estructura de los Sistemas Operativos. transferencia de información entre terminales y procesos, una sección para almacenamiento de descriptores de archivos y una variable que indica la cantidad de memoria principal. A continuación, el Kernel inicializa un proceso especial, llamado proceso 0. En general, los procesos se crean mediante una llamada a una rutina del sistema (fork), que funciona por un mecanismo de duplicación de procesos. Sin embargo, esto no es suficiente para crear el primero de ellos, por lo que el Kernel asigna una estructura de datos y establece apuntadores a una sección especial de la memoria, llamada tabla de procesos, que contendrá los descriptores de cada uno de los procesos existentes en el sistema. Después de haber creado el proceso 0, se hace una copia del mismo, con lo que se crea el proceso 1; éste muy pronto se encargará de "dar vida" al sistema completo, mediante la activación de otros procesos que también forman parte del núcleo. Es decir, se inicia una cadena de activaciones de procesos. A partir de ese momento se conoce el número 1 como proceso de inicialización del sistema (init). El proceso init es el responsable de establecer la estructura de procesos en Unix. Normalmente, es capaz de crear al menos dos estructuras distintas de procesos: el modo monousuario y el multiusuario. Comienza activando el intérprete del lenguaje de control (Shell) en la terminal principal del sistema y proporcionándole privilegios de "superusuario". En la modalidad de un solo usuario la consola permite iniciar una primera sesión, con privilegios especiales, e impide que las otras líneas de comunicación acepten iniciar sesiones nuevas. Esta modalidad se usa con frecuencia para revisar y reparar sistemas de archivos, realizar pruebas de funciones básicas del sistema y para otras actividades que requieren uso exclusivo de la computadora. Init crea otro proceso, que espera pacientemente a que alguien entre en sesión en alguna línea de comunicación. Cuando esto sucede, realiza ajustes en el protocolo de la línea y ejecuta el programa login, que se encarga de atender inicialmente a los nuevos usuarios. Si la clave del usuario, y la contraseña proporcionadas son las correctas, entonces entra en operación el programa Shell, que en lo sucesivo se encargará de la atención normal del usuario que se dio de alta en esa terminal. A partir de ese momento el responsable de atender al usuario en esa terminal es el intérprete Shell. 9.2.3. Administración de Archivos y Directorios El sistema de archivos de Unix; esta basado en un modelo arborescente y recursivo, en el cual los nodos pueden ser tanto archivos como directorios, y estos últimos pueden contener a su vez directorios o subdirectorios. Debido a esta filosofía, se maneja al sistema con muy pocas órdenes, que permiten una gran gama de posibilidades. Todo archivo de Unix está controlado por múltiples niveles de protección, que especifican los permisos de acceso al mismo. La diferencia que existe entre un archivo de datos, un programa, un manejador de entrada/salida o una instrucción ejecutable se refleja en estos parámetros, de modo que el sistema operativo adquiere características de coherencia y elegancia que lo distinguen. Curso: Sistemas Operativos Multiusuario. 35 Módulo 3: Estructura de los Sistemas Operativos. La raíz del sistema de archivos (conocida como root ) se denota con el símbolo "/", y de ahí se desprende un conjunto de directorios que contienen todos los archivos del sistema de cómputo. Cada directorio, a su vez, funciona como la subraíz de un nuevo árbol que depende de él y que también puede estar formado por directorios o subdirectorios y archivos. Un archivo siempre ocupará el nivel más bajo dentro del árbol, porque de un archivo no pueden depender otros. La shell del sistema proporciona las ordenes necesarias para hacer diversas manipulaciones, como crear directorios, moverse dentro del sistema de archivos, copiarlos, etcétera. 9.2.3.1. Manejo de archivos y de información Como ya se describió, la estructura básica del sistema de archivos es jerárquica, lo que significa que los archivos están almacenados en varios niveles. Se puede tener acceso a cualquier archivo mediante su trayectoria, que especifica su posición absoluta en la jerarquía, y los usuarios pueden cambiar su directorio actual a la posición deseada. Existe también un mecanismo de protección para evitar accesos no autorizados. Los directorios contienen información para cada archivo, que consiste en su nombre y en un número que el Kernel utiliza para manejar la estructura interna del sistema de archivos, conocido como el nodo-i. Hay un nodo-i para cada archivo, que contiene información de su directorio en el disco, su longitud, los modos y las fechas de acceso, el autor, etc. Existe, además, una tabla de descriptores de archivo, que es una estructura de datos residente en el disco magnético. El control del espacio libre en el disco se mantiene mediante una lista ligada de bloques disponibles. Cada bloque contiene la dirección en disco del siguiente bloque en la cadena. El espacio restante contiene las direcciones de grupos de bloques del disco que se encuentren libres. De esta forma, con una operación de E/S, el sistema obtiene un conjunto de bloques libres y un apuntador para conseguir más. Las operaciones de E/S en archivos se llevan a cabo con la ayuda de la correspondiente entrada del nodo-i en la tabla de archivos del sistema. El usuario normalmente desconoce los nodos-i porque las referencias se hacen por el nombre simbólico de la trayectoria. Los procesos emplean internamente funciones primitivas (llamadas al sistema) para tener acceso a los archivos. Toda esta estructura física se maneja mediante la filosofía jerárquica de archivos y directorios ya mencionada, y en forma totalmente transparente para el usuario. Además, desde el punto de vista del sistema operativo, un archivo es muy parecido a un dispositivo. Las ventajas de tratar a los dispositivos de E/S en forma similar a los archivos normales son múltiples: un archivo y un dispositivo de E/S se tornan muy parecidos; los nombres de los archivos y de los dispositivos tienen la misma sintaxis y significado, así que a un programa que espera un nombre de archivo como parámetro puede dársele un nombre de dispositivo (con esto se logra interacción rápida y fácil entre procesos de alto nivel). El sistema Unix ofrece varios niveles de protección para el sistema de archivos, que consisten en asignar a cada archivo el número único de identificación de su dueño, junto con nueve bits de protección, que especifican permisos de lectura, escritura y ejecución para el propietario, para otros miembros de su grupo (definido por el administrador del sistema) y para el resto de los usuarios. Antes de cualquier acceso se verifica su validez consultando estos bits, que residen en el Curso: Sistemas Operativos Multiusuario. 36 Módulo 3: Estructura de los Sistemas Operativos. nodo-i de todo archivo. Además, existen otros tres bits que se emplean para manejos especiales, relacionados con la clave del superusuario. Otra característica de Unix es que no requiere que el conjunto de sistemas de archivos resida en un mismo dispositivo. Es posible definir uno o varios sistemas "desmontables", que residen físicamente en diversas unidades de disco. 9.2.4. Procesos. Manejo del Procesador En Unix se ejecutan programas en un medio llamado "proceso de usuario". Cuando se requiere una función del Kernel, el proceso de usuario hace una llamada especial al sistema y entonces el control pasa temporalmente al núcleo. Para esto es necesario un conjunto de elementos de uso interno. Se conoce como imagen a una especie de fotografía del ambiente de ejecución de un proceso, que incluye una descripción de la memoria, valores de registros generales, status de archivos abiertos, el directorio actual, etcétera. Una imagen es el estado actual de una computadora virtual, dedicada a un proceso en particular. Un proceso se define como la ejecución de una imagen. Mientras el procesador ejecuta un proceso, la imagen debe residir en la memoria principal; durante la ejecución de otros procesos permanece en la memoria principal hasta que aparece un proceso activo de mayor prioridad la obligue a ser copiada al disco. Un proceso puede encontrarse en los siguientes estados: en ejecución; listo para ejecutar, o en espera. Cuando se invoca una función del sistema, el proceso de usuario llama al Kernel como subrutina. Hay un cambio de ambientes y, como resultado, se tiene un proceso del sistema. Estos dos procesos son dos fases del mismo original, que nunca se ejecutan en forma simultánea. Existe una tabla de procesos que contiene una entrada por cada uno de ellos con los datos que requiere el sistema: • Identificación • Direcciones de los segmentos que emplea en la memoria • Información que necesita el scheduler y otros. La entrada de la tabla de procesos se asigna cuando se crea el proceso y se libera cuando éste termina. Para crear un proceso se requiere la inicialización de una entrada en la tabla, así como la creación de segmentos de texto y de datos. Además, es necesario modificar la tabla cuando cambia el estado del proceso o cuando recibe un mensaje de otro (para sincronización, por ejemplo). Cuando un proceso termina, su entrada en la tabla se libera y queda otro disponible para que otro nuevo la utilice. En el sistema operativo Unix los procesos pueden comunicarse internamente entre sí, mediante el envío de mensajes o señales. El mecanismo conocido como interconexión (pipe) crea un canal entre dos procesos mediante una llamada a una rutina del Kernel, y se emplea tanto para pasar datos unidireccionalmente entre las imágenes de ambos, como para sincronizarlos, ya que si un proceso intenta escribir Curso: Sistemas Operativos Multiusuario. 37 Módulo 3: Estructura de los Sistemas Operativos. en un pipe ocupado, debe esperar a que el receptor lea los datos pendientes. Lo mismo ocurre en el caso de una lectura de datos inexistentes: el proceso que intenta leer debe esperar a que el proceso productor deposite los datos en el canal de intercomunicación. Dentro de las tareas del manejo del procesador destaca la asignación dinámica (scheduling), que en Unix resuelve el scheduler mediante un mecanismo de prioridades. Cada proceso tiene asignada una prioridad; las prioridades de los procesos de usuario son menores que la más pequeña de un proceso del sistema. El "motor" que mantiene en movimiento un esquema de multiprogramación es, por un lado, el conjunto de interrupciones que genera el desempeño de los procesos y, por otro, los constantes recordatorios que hace el reloj del procesador para indicar que se terminó la fracción de tiempo dedicada a cada proceso. En el sistema Unix, las interrupciones son causadas por lo que se conoce como eventos, entre los cuales se consideran: la ejecución de una tarea de entrada/salida; la terminación de los procesos dependientes de otro; la terminación de la fracción de tiempo asignada a un proceso, y la recepción de una señal desde otro proceso. En un sistema de tiempo compartido se divide el tiempo en un determinado número de intervalos o fracciones y se asigna cada una de ellas a un proceso. Además Unix toma en consideración que hay procesos en espera de una operación de E/S y que ya no pueden aprovechar su fracción. Para asegurar una distribución adecuada del procesador entre los procesos se calculan dinámicamente las prioridades de estos últimos, con el fin de determinar cuál será el proceso que se ejecutará cuando se suspenda el proceso activo actual. 9.2.5. Administración de Memoria Dependiendo de la computadora en la que se ejecute, Unix utiliza dos técnicas de manejo de memoria: swapping y memoria virtual. Lo estándar en Unix es un sistema de intercambio de segmentos de un proceso entre memoria principal y memoria secundaria, llamado swapping lo que significa que se debe mover la imagen de un proceso al disco si éste excede la capacidad de la memoria principal, y copiar el proceso completo a memoria secundaria. Es decir, durante su ejecución, los procesos son cambiados de y hacia memoria secundaria conforme se requiera. Si un proceso necesita crecer, pide más memoria al sistema operativo y se le da una nueva sección, lo suficientemente grande para acomodarlo. Entonces, se copia el contenido de la sección usada al área nueva, se libera la sección antigua y se actualizan las tablas de descriptores de procesos. Si no hay suficiente memoria en el momento de la expansión, el proceso se bloquea temporalmente y se le asigna espacio en memoria secundaria. Se copia a disco y, posteriormente, cuando se tiene el espacio adecuado - lo cual sucede normalmente en algunos segundos se devuelve a memoria principal. Está claro que el proceso que se encarga de los intercambios entre memoria y disco (llamado swapper) debe ser especial y jamás podrá perder su posición privilegiada en la memoria central. El Kernel se encarga de que nadie intente siquiera interrumpir este proceso, del cual dependen todos los demás. Este es el proceso 0 mencionado antes. Cuando se decide traer a la memoria principal un Curso: Sistemas Operativos Multiusuario. 38 Módulo 3: Estructura de los Sistemas Operativos. proceso en estado de "listo para ejecutar", se le asigna memoria y se copian allí sus segmentos. Entonces, el proceso cargado compite por el procesador con todos los demás procesos cargados. Si no hay suficiente memoria, el proceso de intercambio examina la tabla de procesos para determinar cuál puede ser interrumpido y llevado al disco. La elección de qué proceso será desactivado y llevado a memoria secundaria se realiza escogiendo entre aquellos que están esperando operaciones lentas (E/S), o que llevan cierto tiempo sin haberse movido al disco. La idea es tratar de repartir en forma equitativa las oportunidades de ejecución entre todos los procesos, tomando en cuenta sus historias recientes y sus patrones de ejecución. Por otra parte, la elección de qué proceso es traído a memoria principal se toma con base al tiempo de residencia en memoria secundaria. El proceso más antiguo es el que se llama primero, con una pequeña penalización para los grandes. Cuando Unix opera en máquinas más grandes, suele disponer de manejo de memoria de paginación por demanda. En algunos sistemas el tamaño de la página en Unix es de 512 bytes; en otros, de 1024. Para reemplazo se usa un algoritmo que mantiene en memoria las páginas empleadas más recientemente. Un sistema de paginación por demanda ofrece muchas ventajas en cuanto a flexibilidad y agilidad en la atención concurrente de múltiples procesos y proporciona, además, memoria virtual, es decir, la capacidad de trabajar con procesos mayores que el de la memoria central. Estos esquemas son bastante complejos y requieren del apoyo de hardware especializado. 9.2.6. Manejo de entradas y salidas El sistema de entrada/salida se divide en dos sistemas complementarios: el estructurado por bloques y el estructurado por caracteres. El primero se usa para manejar cintas y discos magnéticos, y emplea bloques de tamaño fijo (512 o 1024 bytes) para leer o escribir. El segundo se utiliza para atender a las terminales, líneas de comunicación e impresoras, y funciona byte por byte. En general, el sistema Unix emplea programas especiales conocidos como manejadores (drivers) para atender a cada familia de dispositivos de E/S. Los procesos se comunican con los dispositivos mediante llamadas a su manejador. El funcionamiento de estos manejadores en los sistemas UNIX es muy parecido a los archivos: sobre los manejadores se puede leer y escribir, como si de auténticos archivos o directorios se tratase. Este funcionamiento hace que la utilización de los manejadores de dispositivos sea muy simple. Para realizar las operaciones de E/S, el Sistema Operativo emplea una serie de rutinas generales para los distintos dispositivos. Esto permite que desde el punto de vista del usuario, no se encuentren grandes diferencias entre emplear un dispositivo y otro. No existe distinción entre acceso aleatorio y secuencial, ni hay un tamaño de registro lógico impuesto por el sistema. El tamaño de un archivo ordinario está determinado por el número de bytes escritos en él; no es necesario predeterminar el tamaño de un archivo. El sistema mantiene una lista de áreas de almacenamiento temporal (buffers), asignadas a los dispositivos de bloques. El Kernel usa estos buffers con el objeto de reducir el tráfico de E/S. Cuando un programa solicita una transferencia, se busca primero en los buffers internos para ver si el bloque que se requiere ya se Curso: Sistemas Operativos Multiusuario. 39 Módulo 3: Estructura de los Sistemas Operativos. encuentra en la memoria principal, resultado de una operación de lectura anterior. Si es así, entonces no será necesario realizar la operación física de entrada o salida. Existe todo un mecanismo de manipulación interna de buffers, necesario para controlar el flujo de datos entre los dispositivos de bloques (y de caracteres) y los programas que los requieren. Por último, y debido a que los manejadores de los dispositivos son programas escritos en lenguaje C, es relativamente fácil reconfigurar el sistema para ampliar o eliminar dispositivos de E/S en la computadora, así como para incluir tipos nuevos. Curso: Sistemas Operativos Multiusuario. 40