Notas Sistemas Operativos-Modelo de Datos
Las Notas finales de las materias Sistemas Operativos y Modelo de Datos del Periodo 2009-I, ya están publicadas.
http://eduhesc.wordpress.com/tag/notas/
http://eduhesc.wordpress.com/tag/notas/
En un sistema monoprogramado, la memoria principal se divide en dos partes: una parte para el sistema operativo (monitor residente, núcleo) y otra parte para el programa que se ejecuta en ese instante. En un sistema multiprogramado, la parte de “usuario” de la memoria debe subdividirse aún más para hacer sitio a varios procesos. La tarea de subdivisión la lleva a cabo dinámicamente el sistema operativo y se conoce como gestión de memoria.
En un sistema multiprogramado resulta vital una gestión efectiva de la memoria. Si sólo hay unos pocos procesos en memoria, entonces la mayor parte del tiempo estarán esperando a la E/S y el procesador estará desocupado. Por ello, hace falta repartir eficientemente la memoria para meter tantos procesos como sea posible.
REQUISITOS DE LA GESTIÓN DE MEMORIA
Al realizar un estudio de los diversos mecanismos y políticas relacionadas con la gestión de memoria, vale la pena tener en mente los requisitos que se intentan satisfacer: [LIST88] propone cinco requisitos:
Reubicación
En un sistema multiprogramado, la memoria disponible se encuentra normalmente com-partida por varios procesos. En general, el programador no puede conocer por adelantado qué otros programas residirán en memoria en el momento de la ejecución del programa. Además, se busca poder cargar y descargar los procesos activos en la memoria principal para maximizar el uso del procesador, manteniendo una gran reserva de procesos listos para ejecutar. Una vez que un programa haya sido descargado al disco, se limitará a declarar que, cuando vuelva a ser cargado, debe situarse en la misma región de memoria principal que antes.
De este modo, se sabe antes de tiempo dónde debe situarse un programa y hay que permitir que el programa pueda moverse en memoria principal como resultado de un intercambio. Esta situación plantea algunos asuntos técnicos relativos al direccionamiento, tal y como se muestra en la figura 6.1, que representa la imagen de un proceso. Por simplicidad, se supondrá que la imagen del proceso ocupa una región contigua de la memoria principal. Sin duda, el sistema operativo tiene que conocer la ubicación de la información de control del proceso y de la pila de ejecución, así como el punto de partida para comenzar la ejecución del programa para dicho proceso. Puesto que el sistema operativo gestiona la memoria y es responsable de traer el proceso a memoria principal, estas direcciones deben ser fáciles de conseguir. Además, el procesador debe ocuparse de las referencias a memoria dentro del programa. Las instrucciones de bifurcación deben contener la dirección que haga referencia a la instrucción que se vaya a ejecutar a continuación. Las instrucciones que hagan referencia a datos deben contener la dirección del byte o de la palabra de datos referenciada. De algún modo, el hardware del procesador y el software del sistema operativo deben ser capaces de traducir las referencias a memoria encontradas en el código del programa a las direcciones físicas reales que reflejen la posición actual del programa en memoria principal.
Protección
Cada proceso debe protegerse contra interferencias no deseadas de otros procesos, tanto accidentales como intencionadas. Así pues, el código de un proceso no puede hacer referencia a posiciones de memoria de otros procesos, con fines de lectura o escritura, sin permiso. Hasta cierto punto, satisfacer las exigencias de reubicación aumenta la dificultad de satisfacción de las exigencias de protección. Puesto que se desconoce la ubicación de un programa en memoria principal, es imposible comprobar las direcciones absolutas durante la compilación para asegurar la protección. Es más, la mayoría de los lenguajes de programación permiten el cálculo dinámico de direcciones durante la ejecución, generando, por ejemplo, un índice de un vector o un puntero a una estructura de datos. Por tanto, todas las referencias a memoria generadas por un proceso deben comprobarse durante la ejecución para asegurar que sólo hacen referencia al espacio de memoria destinado a dicho proceso. Afortunadamente, como se verá, los mecanismos que respaldan la reubicación también forman parte básica del cumplimiento de las necesidades de protección.
La imagen del proceso de la figura 6.1 ilustra las necesidades de protección. Normalmente, un proceso de usuario no puede acceder a ninguna parte del sistema operativo, tanto programa como datos. De nuevo, el programa de un proceso no puede en general bifurcar hacia una instrucción de otro proceso. Además, sin un acuerdo especial, el programa de un proceso no puede acceder al área de datos de otro proceso. El procesador debe ser capaz de abandonar tales instrucciones en el momento de la ejecución.
Nótese que, en los términos del ejemplo, las exigencias de protección de memoria pueden ser satisfechas por el procesador (hardware) en vez de por el sistema operativo (software). Esto es debido a que el sistema operativo no puede anticiparse a todas las referencias a memoria que hará un programa. Incluso si tal anticipación fuera posible, sería prohibitivo en términos de tiempo consumido el proteger cada programa por adelantado de posibles violaciones de referencias a memoria. Así pues, sólo es posible evaluar la tolerancia de una referencia a memoria (acceso a datos o bifurcación) durante la ejecución de la instrucción que realiza la referencia. Para llevar esto a cabo, el hardware del procesador debe poseer dicha capacidad.
Compartición
Cualquier mecanismo de protección que se implemente debe tener la flexibilidad de permitir el acceso de varios procesos a la misma zona de memoria principal. Por ejemplo, si una serie de procesos están ejecutando el mismo programa, resultaría beneficioso permitir a cada proceso que acceda a la misma copia del programa, en lugar de tener cada uno su propía copia aparte. Los procesos que cooperan en una tarea pueden necesitar acceso compartido a la misma estructura de datos. El sistema de gestión de memoria debe, por tanto, permitir accesos controlados a las áreas compartidas de la memoria, sin comprometer la protección básica. De nuevo, se verá que los mecanismos empleados para respaldar la reubicación forman parte básica de las capacidades de compartición.
Organización Lógica
De forma casi invariable, la memoria principal de un sistema informático se organiza como un espacio de direcciones lineal o unidimensional que consta de una secuencia de bytes o palabras. La memoria secundaria, a nivel físico, se organiza de forma similar. Si bien esta organización refleja fielmente el hardware de la máquina, no se corresponde con la forma en la que los programas están construidos habitualmente. La mayoría de los programas se organizan en módulos, algunos de los cuales no son modificables (sólo lectura, sólo ejecución) y otros contienen datos que se pueden modificar. Si el sistema operativo y el hardware del computador pueden tratar de forma efectiva los programas de usuario y los datos en forma de módulos de algún tipo, se conseguirá una serie de ventajas, tales como:
1. Los módulos pueden escribirse y compilarse independientemente, mientras que el sistema resuelve durante la ejecución todas las referencias de un módulo a otro.
2. Con un escaso coste adicional, pueden otorgarse varios grados de protección (sólo lectura, sólo ejecución) a los distintos módulos.
3. Es posible introducir mecanismos por medio de los cuales los procesos puedan compartir módulos. La ventaja de ofrecer compartición a nivel de módulo es que esto se corresponde con la visión del problema que tiene el usuario y, por tanto, es fácil para el usuario especificar la compartición que desea.
La herramienta que más fácilmente satisface estas necesidades es la segmentación, que es una de las técnicas de gestión de memoria estudiadas en este capítulo.
Organización Física
La memoria del computador se organiza en, al menos, dos niveles: memoria principal y memoria secundaria. La memoria principal ofrece un acceso rápido con un coste relativamente alto. Además, la memoria principal es volátil; esto es, no proporciona almacenamiento permanente. La memoria secundaria es más lenta y barata que la memoria principal y, normalmente, no es volátil. De este modo, una memoria secundaria de gran capacidad puede permitir un almacenamiento a largo plazo de programas y datos, al tiempo que una memoria principal pequeña mantiene los programas y datos de uso actual.
En este esquema a dos niveles, la organización del flujo de información entre la memoria principal y la secundaria tiene un gran interés en el sistema. La responsabilidad de este flujo podría asignarse al programador, pero esto es impracticable e indeseable, debido a dos razones:
1. La memoria principal disponible para un programa y sus datos puede ser insuficiente. En este caso, el programador debe emplear una práctica que se conoce como superposición (overlaying), en la cual el programa y los datos se organizan de tal forma que puede haber varios módulos asignados a la misma región de memoria, con un programa principal responsable del intercambio de los módulos según se necesite. Incluso con la ayuda de herramientas de compilación, la programación superpuesta malgasta el tiempo del programador.
2. En un entorno multiprogramado, el programador no conoce durante la codificación cuánto espacio habrá disponible o dónde estará este espacio.
Resulta claro entonces que la tarea de mover información entre los dos niveles de memoria debe ser responsabilidad del sistema. Esta tarea es la esencia de la gestión de memoria.
CARGA DE PROGRAMAS EN MEMORIA PRINCIPAL
La tarea central de cualquier sistema de gestión de memoria es traer los programas a memoria principal para su ejecución en el procesador. En casi todos los sistemas multiprogramados modernos, esta tarea supone un esquema sofisticado conocido como memoria virtual. La memoria virtual está, a su vez, basada en el uso de una de dos técnicas básicas; segmentación y/o paginación. Antes de ver estás técnicas de memoria virtual, se debe preparar el terreno considerando técnicas más simples que no requieren el uso de memoria virtual. Una de estas técnicas, la partición, se ha venido usando con distintas variantes en algunos sistemas operativos ahora obsoletos. Las otras dos técnicas, la paginación simple y la segmentación simple, no se usan en solitario. No obstante, el estudio de la memoria virtual resultará más sencillo si se consideran en primer lugar estas dos técnicas, sin tener en cuenta la memoria virtual.
Partición fija
En la mayoría de los esquemas de gestión de memoria, se puede suponer que el sistema operativo ocupa una parte fija de memoria principal y que el resto de la memoria está disponible para ser usado por varios procesos. El esquema más sencillo de gestión de la memoria disponible es dividirla en regiones con límites fijos.
Tamaños de Partición
En la figura 6.2 se ofrecen ejemplos de dos alternativas de partición fija. Una posibilidad es emplear particiones de igual tamaño. En este caso, cualquier proceso cuyo tamaño sea menor o igual que el tamaño de la partición puede cargarse en cualquier partición libre. Si todas las particiones están ocupadas y no hay procesos residentes en estado Listo o Ejecutando, el sistema operativo puede sacar un proceso de alguna de las particiones y cargar otro proceso de forma que haya trabajo para el procesador.
Las particiones fijas de igual tamaño plantean dos dificultades:
• Un programa puede ser demasiado grande para caber en la partición. En este caso, el programador debe diseñar el programa mediante superposiciones, para que sólo una parte del programa esté en memoria principal en cada instante. Cuando se necesita un módulo que no está presente, el programa de usuario debe cargar dicho módulo en la partición del programa, superponiéndose a los programas y datos que se encuentren en ella
•El uso de memoria principal es extremadamente ineficiente. Cualquier programa, sin im-portar lo pequeño que sea, ocupará una partición completa. En el ejemplo, puede haber un programa que ocupe menos de 128Kb de memoria y, aún así, ocuparía una partición de 512Kb cada vez que se cargase. Este fenómeno, en el que se malgasta el espacio interno de una partición cuando el bloque de datos cargado sea más pequeño que la partición, se denomina fragmentación interna.
Pueden reducirse, aunque no solventarse, ambos problemas, por medio del empleo de particiones de tamaños distintos, como se muestra en la figura 5.2b. En este ejemplo, los programas de hasta 1Mb pueden alojarse sin superposición. Las particiones menores de 512K permiten alojar programas más pequeños con un desperdicio menor.
Con particiones del mismo tamaño, la ubicación de un proceso en memoria es trivial. Mientras haya alguna partición libre, puede cargarse un proceso en esa partición. Puesto que todas las particiones son de igual tamaño, no importa la partición que se use. Si todas las particiones están ocupadas con procesos que no están listos para ejecutar, uno de esos procesos debe sacarse y hacer sitio para un nuevo proceso. Cuál debe expulsarse es una decisión de planificación; este punto se tratará en el capítulo 8.
Con particiones de distintos tamaños, hay dos maneras posibles de asignar los procesos a las particiones. La forma más simple es asignar cada proceso a la partición más pequeña en la que quepa’. En este caso, hace falta una cola de planificación para cada partición, que albergue los procesos expulsados cuyo destinado es dicha partición (figura 6.3a). La ventaja de este enfoque es que los procesos están siempre asignados de forma que se minimiza la memoria desperdiciada dentro de cada partición.
Sin embargo, aunque esta técnica parece óptima desde el punto de vista de una partición in-dividual, no lo es desde el punto de vista del sistema global. Considérese el caso de la figura 6.2b, por ejemplo, donde no hay procesos con un tamaño comprendido entre 768K y 1M en un determinado instante. En este caso, la partición de 768K permanecerá sin usar, incluso aunque algún proceso más pequeño pudiera haber sido asignado a la misma. Así pues, una solución mejor sería emplear una única cola para todos los procesos (figura 6.3b). Cuando se va a cargar un proceso en memoria principal, se selecciona la partición más pequeña disponible que pueda albergar al proceso. Si todas las particiones están ocupadas, se debe tomar una decisión de intercambio. Puede darse preferencia al intercambio de la partición más pequeña que pueda contener al proceso entrante. También es posible considerar otros factores, tales como priori-dades y preferencia para descargar procesos bloqueados antes que procesos listos.
El uso de particiones de distinto tamaño proporciona cierto grado de flexibilidad a las par-ticiones fijas. Además, ambos tipos de esquema de partición fija son relativamente simples y exigen un software del sistema operativo y una sobrecarga de procesamiento mínimos. Sin embargo, se plantean los problemas siguientes:
• El número de particiones especificadas en el momento de la generación del sistema limita el número de procesos activos (no suspendidos) del sistema.
• Puesto que los tamaños de partición se programan en el momento de la generación del sistema, los trabajos pequeños no hacen un uso eficiente del espacio de las particiones. En un entorno en el que los requisitos básicos de almacenamiento de todos los procesos se conocen de antemano, puede ser una técnica razonable, pero, en la mayoría de los casos, ineficiente.
El uso de la partición fija es casi nulo hoy día. Como ejemplo de un sistema operativo fructuoso que empleaba está técnica se tiene un antiguo sistema operativo de grandes computadores de IBM, el OS/MFT (Multiprogramación con un número Fijo de Tareas).
Partición Dinámica
Para superar algunas de las dificultades de la partición estática, se desarrolló una solución denominada partición dinámica. Otra vez, este enfoque ha sido superado de largo por técnicas de gestión de memoria más sofisticadas. Un sistema operativo importante que empleaba esta técnica fue el antiguo OS/MVT (Multiprogramación con un número Variable de Tareas), para grandes computadores de IBM.
Con la partición dinámica, las particiones son variables en número y longitud. Cuando se trae un proceso a memoria principal, se le asigna exactamente tanta memoria como necesita y no más. En la figura 6.4 se muestra un ejemplo que usa 1MB de memoria principal. Al principio, la memoria principal está vacía, exceptuando el sistema operativo (figura 6.4a). Se cargan los tres primeros procesos, empezando en donde acaba el sistema operativo y ocupando sólo un espacio suficiente para cada proceso (figuras 6.4b, c y d). Esto deja un “hueco” al final de la memoria demasiado pequeño para un cuarto proceso. En algún momento, ninguno de los procesos en memoria está listo. Así pues, el sistema operativo saca al proceso 2 (figura 6.4e), que deja sitio suficiente para cargar un nuevo proceso, el proceso 4 (figura 6.4f). Puesto que el proceso 4 es más pequeño que el proceso 2, se crea otro hueco pequeño. Más tarde, se alcanza un punto en el que ninguno de los procesos que están en memoria principal están listos y el proceso 2, que está en estado Listo, pero suspendido, está disponible. Puesto que no hay suficiente sitio en memoria para el proceso 2, el sistema operativo expulsa al proceso 1 (figura 6.4g) y carga de nuevo el proceso 2 (figura 6.4h).
Como se muestra en el ejemplo, este método comienza bien, pero, finalmente, desemboca en una situación en la que hay un gran número de huecos pequeños en memoria. Conforme pasa el tiempo, la memoria comienza a estar más fragmentada y su rendimiento decae. Este fenómeno se denomina fragmentación externa y se refiere al hecho de que la memoria externa a todas las particiones se fragmenta cada vez más, a diferencia de la fragmentación interna, que se comentó anteriormente.
Una técnica para superar la fragmentación externa es la compactación: De vez en cuando, el sistema operativo desplaza los procesos para que estén contiguos de forma que toda la memoria libre quede junta en un bloque. Por ejemplo, en la figura 6.4h, la compactación produce un bloque de memoria libre de 256K. Este hueco puede ser suficiente para cargar un proceso adicional. La dificultad de la compactación está en que es un procedimiento que consume tiempo, por lo que desperdicia tiempo del procesador. La compactación necesita de la capacidad de reubicación dinámica. Es decir, se debe poder mover un programa de una región a otra de memoria principal sin invalidar las referencias a memoria del programa (véase el Apéndice 6A).
Algoritmo de Ubicación
Puesto que la compactación de memoria consume tiempo, atañe al diseñador del sistema operativo decidir adecuadamente cómo asignar un proceso a memoria (como llenar los huecos). Cuando llega el momento de cargar o traer un proceso a memoria principal y, si hay libre más de un bloque de memoria de tamaño suficiente, el sistema operativo debe decidir cuál asignar.
Los tres algoritmos de ubicación que se pueden considerar son el del mejor ajuste (best-fit), el del primer ajuste (first-fit) y el del siguiente ajuste (next-fit). Todos ellos se limitan a elegir entre los bloques de memoria libres que son mayores o iguales que el proceso a traer. El mejor ajuste elige el bloque de tamaño más parecido al solicitado. El primer ajuste comienza recorriendo la memoria desde el principio y escoge el primer bloque disponible que sea suficientemente grande. El siguiente ajuste recorre la memoria desde el lugar de la última ubicación y elige el siguiente bloque disponible que sea suficientemente grande.
La figura 6.5a muestra un ejemplo de configuración de la memoria después de cierto número de ubicaciones y operaciones de descarga de procesos. El último bloque usado fue de 22Kb, de donde se creó una partición de 14Kb. La figura 6.5b muestra la diferencia entre los algoritmos de ubicación del mejor, primer y siguiente ajuste para una solicitud de 16Kb. El mejor ajuste busca en la lista completa de bloques disponibles y emplea el hueco de 18Kb, dejando un fragmento de 2Kb. El primer ajuste genera un fragmento de 6Kb y el siguiente ajuste origina un fragmento de 20Kb.
Cuál de estos métodos es mejor dependerá de la secuencia exacta de intercambios de procesos que se den y del tamaño de estos procesos. Sin embargo, se pueden hacer algunos comentarios generales (pueden consultarse además [BAYS77], [BREN89] y [SHOR75]). El algoritmo del primer ajuste no sólo es el más sencillo, sino que normalmente es también el mejor y más rápido. El algoritmo del siguiente ajuste tiende a generar resultados algo peores que el del primer ajuste. El algoritmo del siguiente ajuste llevará frecuentemente a la asignación de bloques libres del final de la memoria. El resultado es que el bloque de memoria libre más grande, que suele aparecer al final del espacio de memoria, se divide rápidamente en fragmentos pequeños. Así pues, con el siguiente ajuste hará falta una compactación más frecuente. Por otro lado, el algoritmo del primer ajuste puede poblar el extremo inicial de pequeñas particiones libres que es necesario recorrer en las pasadas siguientes del algoritmo. El algoritmo del mejor ajuste, a pesar de su nombre, proporciona en general los peores resultados. Puesto que este algoritmo busca el hueco más pequeño que cumple con los requisitos, garantiza que el fragmento que se deja es lo más pequeño posible. Aunque cada solicitud de memoria desperdicia siempre la menor cantidad, el resultado es que la memoria principal se llena rápidamente de bloques demasiado pequeños como para satisfacer las solicitudes de asignación de memoria. Así pues, se debe compactar más frecuentemente que con los otros algoritmos.
Algoritmos de Reemplazo
En un sistema multiprogramado con particiones dinámicas, habrá algún momento en el que todos los procesos de memoria principal estén en estado bloqueado y la memoria sea insuficiente, incluso tras la compactación, para un proceso adicional. Para evitar desperdiciar el tiempo del procesador esperando a que un proceso activo se desbloquee, el sistema operativo expulsará uno de los procesos de memoria principal para hacer sitio a un proceso nuevo o un proceso Listo, pero suspendido. Por lo tanto, el sistema operativo debe elegir qué proceso reemplazar. Puesto que el tema de los algoritmos de reemplazo se cubre con mayor detalle en varios esquemas de memoria virtual, se aplazará la discusión de estos algoritmos hasta entonces.
Reubicación
Antes de considerar las formas de solucionar los defectos de las técnicas de partición, se debe aclarar un punto oscuro, que tiene relación con la ubicación de los procesos en memoria. Cuando se emplea el esquema de particiones fijas de la figura 6.3a, se puede esperar que un proceso sea asignado siempre a la misma partición. Es decir, la partición que se selecciona cuando se carga un nuevo proceso será la misma que se emplee siempre para devolver ese proceso a memoria, tras haber sido sacado. En este caso, se puede emplear un cargador sencillo, tal como se describe en el Apéndice 6A: Cuando el proceso se carga por primera vez, todas las referencias relativas a memoria en el código se reemplazan por direcciones absolutas de memoria principal, determinadas por la dirección base del proceso cargado.
En el caso de particiones de igual tamaño y en el caso de una cola única de procesos para particiones de distinto tamaño, un proceso puede ocupar diferentes particiones a lo largo de su vida. Cuando al principio se crea la imagen de un proceso, se cargará en alguna partición de memoria principal. Posteriormente, el proceso puede ser descargado; cuando, más tarde, vuelva a ser cargado, podrá asignársele una partición distinta de la anterior. Esto mismo se cumple con particiones dinámicas. Obsérvese en las figuras 6.4c y 6.4h que el proceso 2 ocupa dos regiones de memoria distintas en las dos ocasiones en las que se le trae a memoria. Es más, cuando se usa compactación, los procesos son desplazados durante su estancia en memoria principal.
Figura 6.6 Soporte de Hardware para la Reubicacion
Considérese ahora un proceso en memoria que incluya instrucciones y datos. Las instrucciones contendrán referencias a memoria de los dos tipos siguientes:
Ahora se demostrará que estas instrucciones no son fijas, sino que cambian cada vez que se intercambia o desplaza un proceso. Para resolver este problema, se realiza una distinción entre varios tipos de direcciones. Una dirección lógica es una referencia a una posición de memoria independiente de la asignación actual de datos a memoria; se debe hacer una traducción a dirección física antes de poder realizar un acceso a memoria. Una dirección relativa es un caso particular de dirección lógica, en el cual la dirección se expresa como una posición relativa a algún punto conocido, habitualmente el comienzo del programa. Una dirección física o dirección absoluta, es una posición real en memoria principal.
Los programas que emplean direcciones relativas en memoria se cargan por medio de car-gadores dinámicos durante la ejecución (véase el estudio del Apéndice 6A). Esto significa que todas las referencias a memoria en el proceso cargado son relativas al origen del programa. Así pues, se necesita en el hardware un medio para traducir las direcciones relativas a direcciones físicas en memoria principal en el momento de la ejecución de la instrucción que contiene la referencia.
Cuando un proceso pasa a estado Ejecutando, se carga con la dirección en memoria principal del proceso un registro especial del procesador, a veces denominado registro base. Existe también un registro límite que indica la posición final del programa; estos valores deben asignarse cuando se carga el programa en memoria o cuando se carga la imagen del proceso. A lo largo de la ejecución del proceso se encuentran direcciones relativas. Estas direcciones incluyen los contenidos del registro de instrucción, las direcciones que aparecen en las instrucciones de bifurcación y llamada, y las direcciones de datos que aparecen en las instrucciones de carga y almacenamiento. Cada una de estas direcciones relativas pasa por dos etapas de manipulación en el procesador.
En primer lugar, se añade el valor del registro base a la dirección relativa para obtener una dirección absoluta. En segundo lugar, la dirección obtenida se compara con el valor del registro límite. Si la dirección está dentro de los omites, se puede proceder con la ejecución de la instrucción. En otro caso, se genera una interrupción al sistema operativo, que debe responder al error de algún modo.
El esquema de la figura 6.6 permite a los programas cargarse y descargarse de memoria a lo largo de la ejecución. También proporciona una medida de protección: Cada imagen de proceso está aislada por el contenido de los registros base y límite, y es segura contra accesos no desea-dos de otros procesos.
Paginación Simple
Tanto las particiones de tamaño fijo como las de tamaño variable hacen un uso ineficiente de la memoria; las primeras generan fragmentación interna, mientras que las segundas originan fragmentación externa. Supóngase, no obstante, que la memoria principal se encuentra particionada en trozos iguales de tamaño fijo relativamente pequeños y que cada proceso está dividido también en pequeños trozos de tamaño fijo y del mismo tamaño que los de memoria. En tal caso, los trozos del proceso, conocidos como páginas, pueden asignarse a los trozos libres de memoria, conocidos como marcos o marcos de página. En este apartado se verá que el espacio malgastado en memoria para cada proceso por fragmentación interna consta sólo de una fracción de la última página del proceso. Además, no hay fragmentación externa.
Continuando con el ejemplo, las cinco páginas del proceso D se cargan en los marcos 4, 5, 6, 11 y 12. La figura 6.8 muestra las distintas tablas de páginas en este instante. Cada tabla de páginas contiene una entrada por cada página del proceso, por lo que la tabla se indexa fácilmente por número de página (comenzando en la página 0). En cada entrada de la tabla de páginas se encuentra el número de marco en memoria, si lo hay, que alberga la página correspondiente. Además, el sistema operativo mantiene una lista de marcos libres con todos los marcos de memoria que actualmente están vacíos y disponibles para las páginas.
Así pues, se puede comprobar que la paginación simple, tal y como se describe, es similar a la partición estática. Las diferencias están en que, con paginación, las particiones son algo más pequeñas, un programa puede ocupar más de una partición y éstas no tienen por qué estar contiguas.
En el ejemplo (figura 6.9b), n=6 y m=10. Para la traducción de direcciones hay que dar los siguientes pasos:
• Obtener el número de página de los n bits más significativos de la dirección lógica.
• Emplear el número de página como índice en la tabla de páginas del proceso para encontrar el número de marco k.
• El comienzo de la dirección física del marco es k x 2m y la dirección física del byte referenciado es este número más el desplazamiento. No hace falta calcular esta dirección física, sino que se construye fácilmente concatenando el número de marco con el desplazamiento.
Resumiendo, mediante la paginación simple, la memoria principal se divide en pequeños marcos del mismo tamaño. Cada proceso se divide en páginas del tamaño del marco; los procesos pequeños necesitaran pocas páginas, mientras que los procesos grandes necesitarán más. Cuando se introduce un proceso en memoria, se cargan todas sus páginas en los marcos libres y se rellena su tabla de páginas. Esta técnica resuelve la mayoría de los problemas inherentes a la partición.
Segmentación Simple
Otro modo de subdividir el programa es la segmentación. En este caso, el programa y sus datos asociados se dividen en un conjunto de segmentos. No es necesario que todos los segmentos de todos los programas tengan la misma longitud, aunque existe una longitud máxima de segmento. Como en la paginación, una dirección lógica segmentada consta de dos partes, en este caso un número de segmento y un desplazamiento.
Como consecuencia del empleo de segmentos de distinto tamaño, la segmentación resulta similar a la partición dinámica. En ausencia de un esquema de superposición o del uso de memoria virtual, sería necesario cargar en memoria todos los segmentos de un programa para su ejecución. La diferencia, en comparación con la partición dinámica, radica en que, con segmentación, un programa puede ocupar más de una partición y éstas no tienen por qué estar contiguas. La segmentación elimina la fragmentación interna, pero, como la partición dinámica, sufre de fragmentación externa. Sin embargo, debido a que los procesos se dividen en un conjunto de partes más pequeñas, la fragmentación externa será menor.
Mientras que la paginación es transparente al programador, la segmentación es generalmente visible y se proporciona como una comodidad para la organización de los programas y datos. Normalmente, el programador o el compilador asigna los programas y los datos a diferentes segmentos. En aras de la programación modular, el programa o los datos pueden ser divididos de nuevo en diferentes segmentos. El principal inconveniente de este servicio es que el programador debe ser consciente de la limitación de tamaño máximo de los segmentos.
Otra consecuencia del tamaño desigual de los segmentos es que no hay una correspondencia simple entre las direcciones lógicas y las direcciones físicas. De forma análoga a la paginación, un esquema de segmentación simple hará uso de una tabla de segmentos para cada proceso y una lista de bloques libres en memoria principal. Cada entrada de tabla de segmentos tendría que contener la dirección de comienzo del segmento correspondiente en memoria principal. La entrada deberá proporcionar también la longitud del segmento para asegurar que no se usan direcciones no válidas. Cuando un proceso pasa al estado Ejecutando, se carga la dirección de su tabla de segmentos en un registro especial del hardware de gestión de memoria. Para la traducción de direcciones hay que dar los siguientes pasos:
En definitiva, con segmentación simple, un proceso se divide en varios segmentos que no tienen por qué ser del mismo tamaño. Cuando un proceso se introduce en memoria, se cargan todos sus segmentos en regiones de memoria libres y se rellena la tabla de segmentos.
Segmentación
Consecuencias de la Memoria Virtual
La segmentación permite al programador contemplar la memoria como si constara de varios espacios de direcciones o segmentos. Con memoria virtual, el programador no necesita pre-ocuparse de las limitaciones de memoria impuestas por la memoria principal. Los segmentos pueden ser de distintos tamaños, incluso de forma dinámica. Las referencias a memoria constan de una dirección de la forma (número de segmento, desplazamiento).
Esta organización ofrece al programador varias ventajas sobre un espacio de direcciones no segmentado:
1. Simplifica el manejo de estructuras de datos crecientes. Si el programador no conoce a priori cuan larga puede llegar a ser una estructura de datos determinada, es necesario suponerlo a menos que se permitan tamaños de segmento dinámicos. Con memoria virtual segmentada, a cada estructura de datos se le puede asignar a su propio segmento y el sistema operativo expandirá o reducirá el segmento cuando se necesite. Si un segmento necesita expandirse en memoria y no dispone de suficiente sitio, el sistema operativo puede mover el segmento a un área mayor de la memoria principal, si la hay disponible, o descargarlo. En este último caso, el segmento agrandado será devuelto a memoria en la siguiente ocasión.
2. Permite modificar y recompilar los programas independientemente, sin que sea necesario recompilar o volver a montar el conjunto de programas por completo. Esto se puede llevar nuevamente a cabo gracias al uso de varios segmentos.
3. Se presta a la compartición entre procesos. Un programador puede situar un programa de utilidades o una tabla de datos en un segmento que pueda ser referenciado por otros procesos.
4. Se presta a la protección. Puesto que un segmento puede ser construido para albergar un conjunto de procedimientos y datos bien definido, el programador o el administrador del sistema podrá asignar los permisos de acceso de la forma adecuada.
| Grupo | Integrantes | Virus | Antivirus |
| 1 | 18,092,206 18,557,534 19,821,204 | MELISSA | SOPHOS |
| 2 | 17,303,977 18,555,561 19,633,791 | ILOVEYOU | AVG |
| 3 | 12,964,106 16,821,948 18,817,792 | ELK CLONER | SYMANTEC |
| 4 | 15,761,414 16,902,409 17,691,394 | CONFICKER | MCAFEE |
| 5 | 17,742,192 18,555,747 19,354,485 | CHI | TRENDMICRO |
| 6 | 10,865,648 17,119,821 17,459,860 | MICHEANGELO | ESET |
| 7 | 17,529,174 18,556,222 18,556,795 | NIMDA | KASPERSKY |
| 8 | 17,974,346 18,954,208 19,407,544 | CODE RED | CLAM |
| 9 | 14,547,071 15,578,617 | BANGLE | PANDA |
Los Sistemas Operativos de tiempo real son aquellos en los cuales no tiene importancia el usuario, sino los procesos. Por lo general, están subutilizados sus recursos con la finalidad de prestar atención a los procesos en el momento que lo requieran. se utilizan en entornos donde son procesados un gran número de sucesos o eventos.
Muchos Sistemas Operativos de tiempo real son construidos para aplicaciones muy específicas como control de tráfico aéreo, bolsas de valores, control de refinerías, control de laminadores. También en el ramo automovilístico y de la electrónica de consumo, las aplicaciones de tiempo real están creciendo muy rápidamente. Otros campos de aplicación de los Sistemas Operativos de tiempo real son los siguientes:
Algunos ejemplos de Sistemas Operativos de tiempo real son: VxWorks, Solaris, Lyns OS y Spectra. Los Sistemas Operativos de tiempo real, cuentan con las siguientes características:
Se distinguen por sus habilidades para poder soportar la ejecución de dos o más trabajos activos (que se están ejecutado) al mismo tiempo. Esto trae como resultado que la Unidad Central de Procesamiento (CPU) siempre tenga alguna tarea que ejecutar, aprovechando al máximo su utilización.
Su objetivo es tener a varias tareas en la memoria principal, de manera que cada uno está usando el procesador, o un procesador distinto, es decir, involucra máquinas con más de una CPU.
Sistemas Operativos como UNIX, Windows 95, Windows 98, Windows NT, MAC-OS, OS/2, soportan la multitarea.
Las características de un Sistema Operativo de multiprogramación o multitarea son las siguientes:
Permiten la simulación de que el sistema y sus recursos son todos para cada usuario. El usuario hace una petición a la computadora, esta la procesa tan pronto como le es posible, y la respuesta aparecerá en la terminal del usuario.
El tiempo compartido, o multitareas, es una extensión lógica de la multiprogramación, Se ejecutan múltiples trabajos mientras la CPU se conmuta entre ellos, pero la conmutación es tan frecuente que los usuarios pueden interactuar con cada programa durante su ejecución.
Un sistema de computador interactivo, o manual, permite la comunicación en línea entre el usuario y el sistema. El usuario da instrucciones al sistema operativo o a un programa directamente, y recibe una respuesta inmediata. Por lo regular, se utiliza el teclado para proporcionar entradas, y las salidas se envían a una pantalla
Los principales recursos del sistema, el procesador, la memoria, dispositivos de E/S, son continuamente utilizados entre los diversos usuarios, dando a cada usuario la ilusión de que tiene el sistema dedicado para sí mismo. Esto trae como consecuencia una gran carga de trabajo al Sistema Operativo, principalmente en la administración de memoria principal y secundaria.
Ejemplos de Sistemas Operativos de tiempo compartido son Multics, OS/360 y DEC-10.
Características de los Sistemas Operativos de tiempo compartido:
Un proceso es básicamente un programa en ejecución y, de una forma un poco más precisa, como la unidad de procesamiento gestionada por el sistema operativo. El sistema operativo mantiene por cada proceso una serie de estructuras de información que permiten identificar las características de éste, así como los recursos que tiene asignados. Cada proceso tiene asociado un espacio de direcciones, una lista de posiciones de memoria desde algún mínimo (usualmente O) hasta algún máximo, que el proceso puede leer y escribir. El espacio de direcciones contiene el programa ejecutable, los datos del programa, y su pila. A cada proceso también se asocia un conjunto de registros, que incluyen el contador del programa, el apuntador de la pila y otros registros de hardware, así como toda la demás información necesaria para ejecutar el program a.


Nuevo. (New) El Proceso se esta Creando.
Ejecución. (Running) En este estado está el proceso que está siendo ejecutado por el procesador, es decir, que está en fase de procesamiento. En esta fase el estado del proceso reside en los registros del procesador.
Bloqueado o En Espera (Waiting) Un proceso bloqueado está esperando a que ocurra un evento y no puede seguir ejecutando hasta que suceda el evento. Una situación típica de proceso bloqueado se produce cuando el proceso solicita una operación de E/S. Hasta que no termina esta operación, el proceso queda bloqueado. En esta fase, el estado del proceso reside en el BCP.
Listo. (Ready) Un proceso está listo para ejecutar cuando puede entrar en fase de procesamiento. Dado que puede haber varios procesos en este estado, una de las tareas del sistema operativo será seleccionar aquel que debe pasar a ejecución. El módulo del sistema operativo que toma esta decisión se denomina planificador. En esta fase, el estado del proceso reside en el BCP.
Terminado. (Terminated). El proceso a terminado su ejecución.
Además de los tres estados básicos de ejecución, listo y bloqueado, los procesos pueden estar en los estados de espera y de suspendido. El diagrama de estados completo de un proceso se representa en la Figura siguiente. Los procesos entran en el sistema porque lo solicita un proceso de usuario o porque está prevista su ejecución hatch. Es frecuente tener una lista de procesos batch en espera para ser ejecutados cuando se pueda. El sistema operativo ha de ir analizando dicha lista para lanzar la ejecución de los procesos a medida que disponga de los recursos necesarios. Los procesos salen del sistema cuando mueren, es decir, al ejecutar el servicio correspondiente o al producir algún error irrecuperable.

Cada proceso se representa en el sistema operativo con un bloque de control de proceso (PCB. Process control block), también llamado bloque de control de tarea.
El Bloque de control del proceso ó BCP o en inglés PCB (Process Control Block) es un registro especial donde el sistema operativo agrupa toda la información que necesita conocer respecto a un proceso particular. Cada vez que se crea un proceso el sistema operativo crea el BCP correspondiente para que sirva como descripción en tiempo de ejecución durante toda la vida del proceso.


Cuando el proceso termina, su BCP es borrado y el registro puede ser utilizado para otros procesos. Un proceso resulta conocido para el sistema operativo y por tanto elegible para competir por los recursos del sistema sólo cuando existe un BCP activo asociado a él. El bloque de control de proceso es una estructura de datos con campos para registrar los diferentes aspectos de la ejecución del proceso y de la utilización de recursos. La información almacenada en un BCP incluye típicamente algunos o todos los campos siguientes:
Identificación de Proceso (Process Identificator -PID-, de sus siglas en Inglés): Los identificadores numéricos que se pueden guardar en el bloque de control de proceso incluyen:
Identificador de este proceso
Identificador del proceso que creó a este proceso (el proceso padre)
Identificador del usuario
Registros Visibles para el Usuario Un registro visible para el usuario es aquél al que puede hacerse referencia por medio del lenguaje máquina que ejecuta el procesador.
Registros de Control y de Estado: Hay varios registros del procesador que se emplean para controlar su funcinamiento. Entre estos se incluyen:
Contador de programa: Contiene la dirección de la próxima instrucción a ser tratada.
Códigos de condición: Muestran el resultado de la operación aritmética o lógica más reciente (signo, cero, acarreo, igualdad, desbordamiento).
Información de estado: Incluye los indicadores de habilitación o inhabilitación de interrupciones y el modo de ejecución.
Punteros de pila: Cada proceso tiene una o más pilas LIFO de sistema asociadas. Las pilas se utilizan para almacenar los parámetros y las direcciones de retorno de los procedimientos y de las llamadas al sistema. El puntero de pila siempre apunta a la cima de la pila.
Información de Planificación y de Estado: Es la información que se necesita por el sistema operativo para llevar a cabo sus funciones de planificación. Los elementos típicos de esta información son los siguientes:
Estado del proceso: Define la disposición del proceso para ser planificado para ejecutar (en ejecución, listo, esperando, detenido).
Prioridad: Se puede usar uno o más campos para describir la prioridad de planificación de los procesos. En algunos sistemas se necesitan varios valores (por omisión, actual, la más alta permitida).
Información de planificación: Ésta dependerá del algoritmo de planificación utilizado. Como ejemplos se tienen la cantidad de tiempo que el proceso ha estado esperando y la cantidad de tiempo que el proceso ejecutó la última vez.
Suceso: La identidad del suceso que el proceso está esperando antes de poder reanudarse.
Estructuración de datos: Un proceso puede estar enlazado con otros procesos en una cola, un anillo o alguna otra estructura. Por ejemplo, todos los procesos que están en estado de espera de un nivel determinado de prioridad pueden estar enlazados en una cola. Un proceso puede mostrar una relación padre-hijo (creador-creado) con otro proceso. El bloque de control de proceso puede contener punteros a otros procesos para dar soporte a estas estructuras.
Comunicación entre Procesos: Puede haber varios indicadores, señales y mensajes asociados con la comunicación entre dos procesos independientes. Una parte de esta información o toda ella se puede guardar en el bloque de control de proceso.
Privilegios de los procesos: A los procesos se les otorgan privilegios en términos de la memoria a la que pueden acceder y el tipo de instrucciones que pueden ejecutar. Además, también se pueden aplicar privilegios al uso de los servicios y utilidades del sistema.
Gestión de Memoria: Esta sección puede incluir punteros a las tablas de páginas y/o segmentos que describen la memoria virtual asignada al proceso.
Propiedad de los Recursos y Utilización: Se pueden indicar los recursos controlados por el proceso, tales como los archivos abiertos. También se puede incluir un histórico de la utilización del procesador o de otros recursos; esta información puede ser necesaria para el planificador.

Esta lista es simplemente indicativa, cada sistema operativo tiene su propio diseño de BCP, con el conjunto de metadatos necesarios para la administración. Puede medir desde 32 bits a 1024. Su denominación cambia según el sistema operativo.
Algunos sistemas de multiprogramación incluyen información de mantenimiento con el propósito de facturar a los usuarios individuales el tiempo de procesador, el almacenamiento, las operaciones de E/S y otras utilizaciones de recursos.
Una vez creado, el BCP se rellena con los atributos definidos como parámetros que se hallan en la plantilla del proceso o que son especificados como parámetros de la llamada al sistema operativo crear_proceso. En ese momento el sistema operativo suele asignar valores a otros campos. Por ejemplo, cuando se crea un proceso, los registros e indicadores hardware se fijan a los valores proporcionados por el cargador/enlazador. Cada vez que un proceso queda suspendido, el contenido de los registros del procesador es generalmente guardado en la pila, y el puntero al marco de la pila en cuestión se almacena en el BCP. De este modo los valores de los registros son restaurados cuando el proceso es seleccionado para ejecutarse nuevamente.
El objetivo de la planificación de procesos y procesos ligeros es el reparto del tiempo de procesador entre los procesos que pueden ejecutar. El planificador es el módulo del sistema operativo que realiza la función de seleccionar el proceso en estado de listo que pasa a estado de ejecución, mientras que el activador es el módulo que pone en ejecución el proceso planificado.
Los sistemas pueden incluir varios niveles de planificación de procesos.
La planificación a largo plazo tiene por objetivo añadir nuevos procesos al sistema, tomándolos de la lista de espera. Estos procesos son procesos de tipo batch, en los que no importa el instante preciso en el que se ejecuten (siempre que se cumplan ciertos límites de espera).
La planificación a medio plazo trata la suspensión de procesos. Es la que decide qué procesos pasan a suspendido y cuáles dejan de estar suspendidos. Añade o elimina procesos de memoria principal modificando, por tanto, el grado de multiprogramación.
La planificación a corto plazo se encarga de seleccionar el proceso en estado de listo que pasa a estado de ejecución. Es, por tanto, la que asigna el procesador. También es importante la planificación de entrada/salida. Esta planificación decide el orden en que se ejecutan las operaciones de entrada/salida que están encoladas para cada periférico.
Planificación expropiativa es la estrategia de permitir que procesos lógicamente ejecutables se suspendan temporalmente y contrasta con el método de ejecución hasta terminar de los primeros sistemas por lotes.
Planificación No Expropiativa es la estrategia de no detener o suspender la ejecución hasta terminar.
Se vuelven a considerar ahora los mecanismos que se usan en el sistema operativo y en los lenguajes de programación para dar soporte a la concurrencia. Esta sección comienza con los semáforos.
El principio fundamental es el siguiente: Dos o más procesos pueden cooperar por medio de simples señales, de forma que se pueda obligar a detenerse a un proceso en una posición determinada hasta que reciba una señal específica. Cualquier requisito complicado de coor-dinación puede satisfacerse por medio de la estructura de señales adecuada. Para la señalización, se usan variables especiales llamados semáforosPara transmitir una señal por el Semáforo, los procesos ejecutan la primitiva signal(s). Para recibir una señal del semáforo , los procesos ejecutan la primitiva wait(s); si la señal correspondiente aún no se ha transmitido, el proceso es suspendido hasta que tenga lugar la transmisión.
Para lograr el efecto deseado, se pueden contemplar los semáforos como variables que tienen un valor entero sobre el que se definen las tres operaciones siguientes:
1. Un semáforo puede inicializarse con un valor no negativo.
2. La operación wait decrementa el valor del semáforo. Si el valor se hace negativo, el proceso que ejecuta el wait se bloquea.
3. La operación signal incrementa el valor del semáforo. Si el valor no es positivo, se desbloquea a un proceso bloqueado por una operación wait.
|
1er. Corte |
2do. Corte |
3er. Corte |
||||||||||
|
20% |
10% |
20% |
15% |
10% |
20% |
5% |
Prueba Extra |
75% |
100% |
|||
|
C.I. |
Prueba I |
Taller I |
Prueba II |
Trabajo I |
Taller II |
Prueba III |
Ras |
Nota |
Pts |
Acu |
Acu |
Nota Final |
|
10,865,648 |
11 |
7 |
12 |
5 |
8 |
19 |
5 |
|
0 |
43 |
67 |
13 |
|
12,964,106 |
13 |
9 |
10 |
7 |
8 |
19 |
5 |
|
0 |
47 |
71 |
14 |
|
14,547,071 |
14 |
|
|
|
|
|
|
|
0 |
14 |
14 |
03 |
|
15,578,617 |
14 |
|
|
|
|
|
|
|
0 |
14 |
14 |
03 |
|
15,761,414 |
14 |
9 |
4 |
4 |
5 |
19 |
3 |
|
0 |
36 |
58 |
11 |
|
16,821,948 |
10 |
8 |
3 |
7 |
6 |
20 |
5 |
|
0 |
34 |
59 |
11 |
|
16,902,409 |
11 |
8 |
11 |
4 |
6 |
20 |
5 |
|
0 |
40 |
65 |
13 |
|
17,119,821 |
5 |
7 |
10 |
5 |
5 |
20 |
0 |
|
0 |
32 |
52 |
10 |
|
17,303,977 |
14 |
7 |
12 |
7 |
8 |
20 |
5 |
|
0 |
48 |
73 |
14 |
|
17,459,860 |
10 |
7 |
9 |
5 |
5 |
19 |
0 |
|
0 |
36 |
55 |
11 |
|
17,529,174 |
12 |
8 |
12 |
8 |
8 |
19 |
5 |
|
0 |
48 |
72 |
14 |
|
17,691,394 |
17 |
8 |
14 |
4 |
7 |
18 |
5 |
|
0 |
50 |
73 |
14 |
|
17,742,192 |
16 |
6 |
13 |
6 |
6 |
16 |
4 |
13 |
8 |
47 |
75 |
15 |
|
17,974,346 |
14 |
8 |
12 |
6 |
8 |
20 |
5 |
|
0 |
48 |
73 |
14 |
|
18,092,206 |
7 |
8 |
7 |
6 |
8 |
20 |
5 |
7 |
3 |
36 |
64 |
12 |
|
18,555,561 |
12 |
7 |
10 |
7 |
7 |
18 |
5 |
|
0 |
43 |
66 |
13 |
|
18,555,747 |
12 |
6 |
13 |
6 |
6 |
18 |
5 |
|
0 |
43 |
66 |
13 |
|
18,556,222 |
14 |
6 |
13 |
8 |
8 |
19 |
5 |
|
0 |
49 |
73 |
14 |
|
18,556,795 |
16 |
6 |
12 |
8 |
6 |
19 |
5 |
|
0 |
48 |
72 |
14 |
|
18,557,534 |
5 |
6 |
10 |
6 |
8 |
19 |
0 |
|
0 |
35 |
54 |
10 |
|
18,817,792 |
10 |
9 |
11 |
7 |
8 |
20 |
3 |
|
0 |
45 |
68 |
13 |
|
18,954,208 |
0 |
9 |
13 |
6 |
8 |
18 |
5 |
|
0 |
36 |
59 |
11 |
|
19,354,485 |
17 |
8 |
6 |
6 |
7 |
20 |
5 |
|
0 |
44 |
69 |
13 |
|
19,407,544 |
15 |
9 |
7 |
6 |
5 |
18 |
5 |
7 |
4 |
42 |
69 |
13 |
|
19,633,791 |
17 |
9 |
13 |
7 |
7 |
19 |
5 |
|
0 |
53 |
77 |
15 |
|
19,821,204 |
10 |
6 |
6 |
6 |
5 |
19 |
5 |
|
0 |
33 |
57 |
11 |
|
19,822,179 |
|
|
|
|
|
|
|
|
0 |
0 |
0 |
01 |
Concepto de Sistemas Operativos
Un sistema operativo es un software de sistema, es decir, un conjunto de programas de computadora destinado a permitir una administración eficaz de sus recursos. Comienza a trabajar cuando se enciende el computador, y gestiona el hardware de la máquina desde los niveles más básicos, permitiendo también la interacción con el usuario.
(Fuente: wikipedia.com)
Conjunto de programas de base que controla al computador y que actúa de intermediario entre el usuario, el computador y los programas de aplicación, traduciendo las órdenes del usuario o de las aplicaciones en instrucciones que puede entender el computador.
(Fuente:profesionaldelainformacion.com)
Funciones básicas de los Sistemas Operativos
Los sistemas operativos, en su condición de capa software que posibilitan y simplifica el manejo de la computadora, desempeñan una serie de funciones básicas esenciales para la gestión del equipo. Entre las más destacables, cada una ejercida por un componente interno (módulo en núcleos monolíticos y servidor en micronúcleos), podemos reseñar las siguientes:
Proporcionar comodidad en el uso de un computador.
Gestionar de manera eficiente los recursos del equipo, ejecutando servicios para los procesos (programas)
Brindar una interfaz al usuario, ejecutando instrucciones (comandos).
Permitir que los cambios debidos al desarrollo del propio SO se puedan realizar sin interferir con los servicios que ya se prestaban (evolutividad).
Un sistema operativo desempeña 5 funciones básicas en la operación de un sistema informático: suministro de interfaz al usuario, administración de recursos, administración de archivos, administración de tareas y servicio de soporte y utilidades.
(Fuente: wikipedia.com)
Características
Conveniencia. Un Sistema Operativo hace más conveniente el uso de una computadora.
Eficiencia. Un Sistema Operativo permite que los recursos de la computadora se usen de la manera más eficiente posible.
Habilidad para evolucionar. Un Sistema Operativo deberá construirse de manera que permita el desarrollo, prueba o introducción efectiva de nuevas funciones del sistema sin interferir con el servicio.
Encargado de administrar el hardware. El Sistema Operativo se encarga de manejar de una mejor manera los recursos de la computadora en cuanto a hardware se refiere, esto es, asignar a cada proceso una parte del procesador para poder compartir los recursos.
Relacionar dispositivos (gestionar a través del kernel). El Sistema Operativo se debe encargar de comunicar a los dispositivos periféricos, cuando el usuario así lo requiera.
Organizar datos para acceso rápido y seguro.
Manejar las comunicaciones en red. El Sistema Operativo permite al usuario manejar con alta facilidad todo lo referente a la instalación y uso de las redes de computadoras.
Procesamiento por bytes de flujo a través del bus de datos.
Facilitar las entradas y salidas. Un Sistema Operativo debe hacerle fácil al usuario el acceso y manejo de los dispositivos de Entrada/Salida de la computadora.
Los recursos clave que un sistema operativo administra son:
Los procesadores
El almacenamiento
Los dispositivos de entrada / salida
Los datos
GENERACIONES DE SISTEMAS OPERATIVOS
Generación Cero (década de 1940)
Los sistemas operativos han ido evolucionando durante los últimos 40 años a través de un número de distintas fases o generaciones que corresponden a décadas. En 1940, las computadoras electrónicas digitales mas nuevas no tenían sistema operativo. Las Máquinas de ese tiempo eran tan primitivas que los programas por lo regular manejaban un bit a la vez en columnas de switch’s mecánicos. Eventualmente los programas de lenguaje máquina manejaban tarjetas perforadas, y lenguajes ensamblador fueron desarrollados para agilizar el proceso de programación. Los usuarios tenían completo acceso al lenguaje de la maquina. Todas las instrucciones eran codificadas a mano.
La primera generacion (1945 – 1955 ) : Tubos de vacio y tableros enchufables
Después del fracaso de los trabajos de Babbage, fueron pocos los avances que se lograron en la construcción de computadoras digitales hasta la Segunda Guerra Mundial. A mediados de la década de 1940, Howard Aiken en Harvard, John von Neumann en el Institute for Advanced Study en Princeton, J. Presper Eckert y William Mauchley en la University of Pennsylvania y Konrad Zuse en Alemania, entre otros, lograron construir máquinas calculadoras usando tubos de vacío. Estas máquinas eran enormes, y ocupaban cuartos enteros con decenas de miles de tubos de vacío, pero eran mucho más lentas que incluso las computadoras personales más baratas de la actualidad.
En esos primeros días, un solo grupo de personas diseñaba, construía, programaba, operaba y mantenía a cada máquina. Toda la programación se realizaba en lenguaje de máquina absoluto, a menudo alambrando tableros de conmutación para controlar las funciones básicas de la máquina. No existían los lenguajes de programación (ni siquiera los de ensamblador). Nadie había oído hablar de los sistemas operativos. La forma de operación usual consistía en que el programador se anotaba para recibir un bloque de tiempo en la hoja de reservaciones colgada en la pared, luego bajaba al cuarto de la máquina, insertaba su tablero de conmutación en la computadora, y pasaba las siguientes horas con la esperanza de que ninguno de los cerca de 20000 tubos de vacío se quemara durante la sesión. Prácticamente todos los problemas eran cálculos numéricos directos, como la producción de tablas de senos y cosenos.
A principios de la década de 1950, la rutina había mejorado un poco con la introducción de las tarjetas perforadas. Ahora era posible escribir programas en tarjetas e introducirlas para ser leídas, en lugar de usar tableros de conmutación; por lo demás, el procedimiento era el mismo.
Caracteristicas
Monitor residente (Carga de programas a memoria)
Procesamiento por lotes (ejecutar programas uno a continuación de otro)
Almacenamiento temporal
La segunda generacion (1955 – 1965 ) : Transistores y sistemas de lote
La introducción del transistor a mediados de la década de 1950 alteró el panorama radicalmente. Las computadoras se hicieron lo bastante confiables como para poderse fabricar y vender a clientes comerciales con la expectativa de que seguirían funcionando el tiempo suficiente para realizar algo de trabajo útil. Por primera vez, había una separación clara entre diseñadores, constructores, operadores, programadores y personal de mantenimiento.
Estas máquinas se encerraban en cuartos de computadora con acondicionamiento de aire especial, con equipos de operadores profesionales para operarias. Sólo las grandes empresas, o las principales dependencias del gobierno o universidades, podían solventar el costo de muchos millones de dólares. Para ejecutar un trabajo (es decir, un programa o serie de programas), un programador escribía primero el programa en papel (en FORTRAN o ensamblador) y luego lo perforaba en tarjetas. Después, llevaba el grupo de tarjetas al cuarto de entrada y lo entregaba a uno de los operadores. Cuando la computadora terminaba el trabajo que estaba ejecutando en ese momento, un operador acudía a la impresora, separaba la salida impresa y la llevaba al cuarto de salida donde el programador podía recogerla después. Luego, el operador tomaba uno de los grupos de tarjeta traídos del cuarto de entrada y lo introducía en el lector. Si se requería el compilador de FORTRAN, el operador tenía que traerlo de un archivero e introducirlo en el lector. Gran parte del tiempo de computadora se desperdiciaba mientras los operadores iban de un lugar a otro, en el cuarto de la máquina.
Dado el alto costo del equipo, no es sorprendente que la gente pronto buscara formas de reducir el desperdicio de tiempo. La solución que se adoptó generalmente fue el sistema por lotes. El principio de este modo de operación consistía en juntar una serie de trabajos en el cuarto de entrada, leerlos y grabarlos en una cinta magnética usando una computadora pequeña y (relativamente) económica, como una IBM 1401, que era muy buena para leer tarjetas, copiar cintas e imprimir salidas, pero no para realizar cálculos numéricos. Otras máquinas, mucho más costosas, como la IBM 7094, se usaban para la computación propiamente dicha.

Después de cerca de una hora de reunir un lote de trabajos, la cinta se rebobinaba y se llevaba al cuarto de la máquina, donde se montaba en una unidad de cinta. El operador cargaba entonces un programa especial (el antepasado del sistema operativo actual), que leía el primer trabajo de la cinta y lo ejecutaba. La salida se escribía en una segunda cinta, en lugar de imprimirse. Cada vez que terminaba un trabajo, el sistema operativo leía automáticamente el siguiente trabajo de la cinta y comenzaba a ejecutarlo. Una vez que estaba listo todo el lote, el operador desmontaba las cintas de entrada y salida, montaba la cinta de entrada del siguiente lote, y llevaba la cinta de salida a una 1401 para la impresión fuera de línea (o sea, no conectada a la computadora principal).
Las computadoras grandes de la segunda generación se usaban primordialmente para cálculos científicos y de ingeniería, como la resolución de ecuaciones diferenciales parciales. Estas máquinas generalmente se programaban en FORTRAN y lenguaje ensamblador. Los sistemas operativos típicos eran FMS (el Fortran Monitor System) e IBSYS, el sistema operativo de IBM para la 7094.
Características
Multiprogramación.
Multiprocesamiento.
Ingenierría de Software: Los sistemas operativos desarrollados durante los 60s tuvieron una enorme conglomeración de software escrito por gente quienes realmente no entendía el software, también como el hardware, tenias que ser ingeniero para ser digno de confianza, entendible y mantenible. Finalmente cuando encontraron y removieron algunos errores que nunca pudieron completar el sistema original. Errores en las fases fáciles de los proyectos no fueron localizados antes de un largo tiempo fueron entregados a los clientes; por este lado los errores fueron enormemente grandes para corregir. La gente obtuvo frecuentemente números grandes de módulos de software empezó a ser fragmentado y reescrito por personas nuevas porque existían módulos que realmente no se entendían. Se tomo mas atención a estos problemas eventualmente científicos de la computación y profesionales en la industria comenzaron a dedicar considerables recursos para el problema de construir sistemas de software. La emergencia de el campo de ingeniería de software y el reconocimiento de la importancia del desarrollo de una disciplinada y desarrollada aproximada a la construcción software digno de confianza, entendible y mantenible fuertemente unidos por la vasta experiencia con algunos de los sistemas operativos desarrollados en los 60s.
La tercera generacion (1965 – 1970 ) : Circuitos integrados ( CI ) y multiprogramacion
A principios de la década de 1960, la mayoría de los fabricantes de computadoras tenían dos líneas de producto distintas y totalmente incompatibles. Por un lado estaban las computadoras científicas a gran escala, orientadas hacia las palabras, como la 7094, que se usaban para cálculos numéricos en ciencias e ingeniería. Por el otro, estaban las computadoras comerciales orientadas hacia los caracteres, como la 1401, que los bancos y las compañías de seguros utilizaban amplia- mente para ordenar e imprimir desde cinta.
IBM trató de resolver simultáneamente ambos problemas introduciendo la System/360. La 360 era una serie de máquinas de software compatible que iban desde tamaños comparables a la 1401 hasta computadoras mucho más potentes que la 7094. Las máquinas diferían sólo en el precio y el rendimiento (memoria máxima, velocidad del procesador, número de dispositivos de E/S permitidos, etc.). Puesto que todas las máquinas tenían la misma arquitectura y conjunto de instrucciones, los programas escritos para una máquina podían ejecutarse en todas las demás, al menos en teoría. Además, la 360 estaba diseñada para manejar computación tanto científica como comercial. Así, una sola familia de máquinas podía satisfacer las necesidades de todos los clientes. En años subsecuentes IBM produjo sucesoras comparables a la línea 360, usando tecnología más moderna, conocidas como series 370, 4300, 3080 y 3090.
A pesar de su enorme tamaño y de sus problemas, os/360 y los sistemas operativos de tercera generación parecidos a él producidos por otros fabricantes de computadoras lograron satisfacer a sus clientes en un grado razonable, y también popularizaron varias técnicas clave que no existían en los sistemas operativos de la segunda generación. Tal vez la más importante de ellas haya sido la multiprogramación.
El problema era el tiempo de espera (en computadores cientificos pocos, pero en los comerciales era muy alto)
La solución a la que se llegó fue dividir la memoria en varias secciones, con un trabajo distinto en cada partición. Mientras un trabajo estaba esperando que terminara su E/S, otro podía estar usando la CPU. Si se podían tener en la memoria principal suficientes trabajos a la vez, la CPU podía mantenerse ocupada casi todo el tiempo. Tener múltiples trabajos en la memoria a la vez requiere hardware especial para proteger cada trabajo contra espionaje o p por parte de los demás, pero la 360 y otros sistemas de tercera generación estaban equipados con este hardware.

Otra característica importante presente en los sistemas operativos de la tercera generación era la capacidad de leer trabajos de las tarjetas al disco tan pronto como se llevaban al cuarto de computadoras. Luego, cada vez que un trabajo terminaba su ejecución, el sistema operativo podía cargar uno nuevo del disco en la partición que había quedado vacía y ejecutarlo. Esta técnica se llama spooling (de “operación simultánea de periféricos en línea”) y también se usaba para la salida. Con spooling, las 1401 ya no eran necesarias, y desapareció una buena parte del transporte de cintas.
Característica
Multiprogramación: alberga a más de un programa en la memoria
Tiempo compartido: existen varios usuarios con un terminal en línea.
Tiempo real: Aceptar y procesar en tiempos muy breves un gran número de operaciones.
Multiprocesador: Trabajar con máquinas que poseen más de un microprocesador. Gracias a esto, el multiprocesador puede ejecutar simultáneamente varios hilos pertenecientes a un mismo proceso o bien a procesos diferentes.
La cuarta generacion (1980 – a nuestros días) : Computadoras personales
Con la invención de los circuitos integrados a gran escala (LSI), chips que contienen miles de transistores en un cm2 de silicio, nació la era de la computadora personal. En términos de arquitectura, las computadoras personales no eran muy diferentes de las minicomputadoras de la clase PDP- 11, pero en términos de precio sí que eran diferentes. Si bien la minicomputadora hacía posible que un departamento de una compañía o universidad tuviera su propia computadora, el chip microprocesador permitía que un solo individuo tuviera su propia computadora personal. Las computadoras personales más potentes empleadas por empresas, universidades e instalaciones del gobierno suelen llamarse estaciones de trabajo, pero en realidad sólo son computadoras personales grandes. Por lo regular estas máquinas están interconectadas mediante una red.
La amplia disponibilidad de la potencia de cómputo, sobre todo la potencia de cómputo altamente interactiva casi siempre acompañada por excelentes gráficos, dio pie al crecimiento de una importante industria productora de software para computadoras personales. Una buena parte de este software era amistoso con el usuario, lo que significa que estaba dirigido a usuarios que no sólo no sabían nada de computación, sino que además no tenían la mínima intención de aprender. Sin duda, esto representaba un cambio drástico respecto al os/360, cuyo lenguaje de control de trabajos, JCL, era tan arcano que llegaron a escribirse libros enteros sobre él.
Dos sistemas operativos dominaron inicialmente el campo de las computadoras personales y las estaciones de trabajo: MS-DOS de Microsoft y UNIX. MS-DOS se usaba ampliamente en la IBM PC y otras máquinas basadas en la CPU Intel 8088 y sus sucesoras, la 80286, 80386 y 80486 (que en adelante llamaremos la 286, 386 y 486, respectivamente) y más tarde la Pentium y Pentium Pro. Aunque la versión inicial de MS-DOS era relativamente primitiva, versiones subsecuentes han incluido características más avanzadas, muchas de ellas tomadas de UNIX. El sucesor de Microsoft para MS-DOS, WINDOWS, originalmente se ejecutaba encima de MS-DOS (es decir, era más un shell que un verdadero sistema operativo), pero a partir de 1995 se produjo una versión autosuficiente de WINDOWS, WINDOWS 95®, de modo que ya no se necesita MS-DOS para apoyarlo. Otro sistema operativo de
Microsoft es WINDOWS NT, que es compatible con WINDOWS 95 en cierto nivel, pero internamente se reescribió desde cero.
El otro competidor importante es UNIX, que domina en las estaciones de trabajo y otras computadoras del extremo alto, como los servidores de red. UNIX es popular sobre todo en máquinas basadas en chips RISC de alto rendimiento. Estas máquinas por lo regular tienen la potencia de cómputo de una minicomputadora, a pesar de estar dedicadas a un solo usuario, por lo que resulta lógico que estén equipadas con un sistema operativo diseñado originalmente para minicomputadoras, a saber, UNIX.
Una tendencia interesante que apareció a mediados de la década de 1980 fue el crecimiento de redes de computadoras personales en las que se ejecutan sistemas operativos de red o sistemas operativos distribuidos. En un sistema operativo de red los usuarios están conscientes de la existencia de múltiples computadoras y pueden ingresar en máquinas re -motas y copiar archivos de una máquina a otra. Cada máquina ejecuta su propio sistema operativo local y tiene su propio usuario o usuarios locales.
(Fuente: Tanenbaum, Andrew,Sistemas Operativos Diseño e Implementacion)
Sistemas de tiempo real
Una forma de sistema operativo de propósito especial es el sistema de tiempo real. Se usa un sistema de tiempo real cuando los requisitos de tiempo de la operación de un procesador o del flujo de datos son estrictos; por ello, a menudo se utilizan como dispositivos de control de aplicaciones dedicadas. Los sensores envían datos al computador, el cual debe analizar estos datos y posiblemente ajustar controles a fin de modificar las entradas de los sensores. Los sistemas que controlan experimentos científicos, los que producen imágenes médicas, los de control industrial y algunos sistemas de exhibición son sistemas de tiempo real. Esta clasificación también incluye algunos sistemas de inyección de combustible para motores de automóviles, controladores de aparatos domésticos y sistemas de armamentos. Un sistema operativo de tiempo real tiene restricciones de tiempo fijas bien definidas. El procesamiento debe efectuarse dentro de los intervalos definidos, o el sistema fallará. Por ejemplo, no es conveniente ordenar a un brazo robot que se detenga después de haber chocado con el automóvil que está construyendo. Se considera que un sistema de tiempo real está funcionando correctamente sólo si produce el resultado correcto dentro de los intervalos de tiempo estipulados. Podemos contrastar este requisito con un con un sistema de tiempo compartido, en el que es deseable (pero no obligatorio) responder rápidamente, o con un sistema por lotes, en el que tal vez no haya restricciones de tiempo.
Hay dos tipos de sistemas de tiempo real:
Sistemas multiprogramación
Aún con el secuenciamiento automático de los trabajos ofrecido por un sistema operativo sencillo por lotes, el procesador está desocupado a menudo. El problema es que los dispositivos de E/S son lentos comparados con el procesador. La figura 2.5 detalla un cálculo representativo. Los números corresponden a un programa que procesa un archivo de registros y ejecuta, en promedio, 100 instrucciones de máquina por cada registro. En este ejemplo, el computador gasta más del 96% del tiempo esperando a que los dispositivos de E/S terminen de transferir sus datos. La figura 2.6 ilustra esta situación. El procesador gasta parte del tiempo ejecutando hasta que encuentra una instrucción de E/S. Entonces debe esperar a que concluya la instrucción de E/S antes de continuar.
Esta ineficiencia no es necesaria. Se sabe que hay memoria suficiente para almacenar el sistema operativo (el monitor residente) y un programa de usuario. Supóngase que hay espacio suficiente para el sistema operativo y tres programas usuarios. Ahora, cuando un trabajo necesite esperar una E/S, el procesador puede cambiar al otro trabajo, que probablemente no estará esperando a la E/S (figura 2.6c). Además, se podría ampliar la memoria para almacenar tres, cuatro o más programas y conmutar entre todos ellos (figura 2.6c). Este proceso es conocido como multiprogramador o multitarea. Éste es el punto central de los sistemas operativos modernos.

Para ilustrar el beneficio de la multiprogramación, considérese un ejemplo basado en uno de Tumer [TURN86]. Sea un computador con 256K palabras de memoria disponible (no utilizadas por el sistema operativo), un disco, una terminal y una impresora. Tres programas, TRABAJO 1, TRABAJ02 y TRABAJOS, son enviados para su ejecución al mismo tiempo . Se suponen unos requisitos mínimos de procesador para el TRABAJ02 y el TRABAJOS y un uso continuado del disco y de la impresora por parte del TRABAJOS. En un sistema sencillo por lotes, estos trabajos serían ejecutados en secuencia. Así pues, el TRABAJO 1 termina en 5 minutos. El TRABAJ02 debe esperar a que transcurran esos 5 minutos y terminar 15 minutos después. El TRABAJOS comienza después de los 20 minutos para terminar SO minutos después del momento en que fue lanzado. Es evidente que hay una infrautilización neta de todos los recursos cuando se promedian los tiempos de uso en el período exigido de SO minutos.
Supóngase ahora que los trabajos se ejecutan concurrentemente en un sistema operativo con monoprogramación. Como hay poca contención de recursos entre los trabajos, cada uno de los tres puede ejecutarse en un tiempo cercano a 1 mínimo mientras coexiste con los otros en el computador (suponiendo que a TRABAJ02 y TRABAJO3 se les adjudica tiempo suficiente de procesador para mantener activas sus operaciones de E/S). El TRABAJO1 requerirá 5 minutos para terminar, pero al finalizar este tiempo, el TRABAJO2 estará terminado en una tercera parte y el TRABAJO3 estará a la mitad. Los tres trabajos habrán terminado dentro de 15 minutos.
Al igual que un sistema sencillo por lotes, un sistema por lotes con multiprogramación tiene que depender de ciertas características del hardware del computador. La característica adicional más notable y útil para la multiprogramación es que el hardware respalde las interrupciones de E/S y el DMA. Con E/S dirigida por interrupciones y con DMA, el procesador puede enviar una orden de E/S para un trabajo y continuar con la ejecución de otro, mientras la E/S es efectuada por el controlador del dispositivo. Cuando termina la operación de E/S, el procesador es interrumpido y el control pasa a un programa de tratamiento de interrupciones del sis-tema operativo. El sistema operativo le pasa entonces el control a otro trabajo.
Los sistemas operativos con multiprogramación son bastante más sofisticados en comparación con los sistemas de monoprogramación o de un solo programa. Para tener varios trabajos listos para ejecutar, éstos deben mantenerse en la memoria principal, lo que requiere cierto tipo de gestión de memoria. Además, si hay varios trabajos listos para ejecutarse, el procesador debe decidir cuál de ellos va a ejecutar, lo que requiere un algoritmo de planificación.
Sistema Multiproceso
Un sistema operativo multiproceso se refiere al número de procesadores del sistema, que es más de uno y éste es capaz de usarlos todos para distribuir su carga de trabajo. Generalmente estos sistemas trabajan de dos formas: simétrica o asimétricamente. Cuando se trabaja de manera asimétrica, el sistema operativo selecciona a uno de los procesadores el cual jugará el papel de procesador maestro y servirá como pivote para distribuir la carga a los demás procesadores, que reciben el nombre de esclavos. Cuando se trabaja de manera simétrica, los procesos o partes de ellos (threads) son enviados indistintamente a cualesquiera de los procesadores disponibles, teniendo, teóricamente, una mejor distribución y equilibrio en la carga de trabajo bajo este esquema.
MULTIPROCESO: Las computadoras que tienen mas de un CPU son llamadas multiproceso. Un sistema operativo multiproceso coordina las operaciones de la computadoras multiprocesadoras. Ya que cada CPU en una computadora de multiproceso puede estar ejecutando una instrucción, el otro procesador queda liberado para procesar otras instrucciones simultáneamente.
Al usar una computadora con capacidades de multiproceso incrementamos su velocidad de respuesta y procesos. Casi todas las computadoras que tienen capacidad de multiproceso ofrecen una gran ventaja.
Los primeros Sistemas Operativos Multiproceso realizaban lo que se conoce como:
Multiproceso asimétrico: Una CPU principal retiene el control global de la computadora, así como el de los otros procesadores. Esto fue un primer paso hacia el multiproceso pero no fue la dirección ideal a seguir ya que la CPU principal podía convertirse en un cuello de botella.
Multiproceso simétrico: En un sistema multiproceso simétrico, no existe una CPU controladora única. La barrera a vencer al implementar el multiproceso simétrico es que los SO tienen que ser rediseñados o diseñados desde el principio para trabajar en u n ambiente multiproceso. Las extensiones de Unix, que soportan multiproceso asimétrico ya están disponibles y las extensiones simétricas se están haciendo disponibles. Windows NT de Microsoft soporta multiproceso simétrico.
Se dice que un thread es la parte activa en memoria y corriendo de un proceso, lo cual puede consistir de un área de memoria, un conjunto de registros con valores específicos, la pila y otros valores de contexto. Un aspecto importante a considerar en estos sistemas es la forma de crear aplicaciones para aprovechar los varios procesadores. Existen aplicaciones que fueron hechas para correr en sistemas monoproceso que no toman ninguna ventaja a menos que el sistema operativo o el compilador detecte secciones de código paralelizable, los cuales son ejecutados al mismo tiempo en procesadores diferentes. Por otro lado, el programador puede modificar sus algoritmos y aprovechar por sí mismo esta facilidad, pero esta última opción las más de las veces es costosa en horas hombre y muy tediosa, obligando al programador a ocupar tanto o más tiempo a la
paralelización que a elaborar el algoritmo inicial.
Sistemas de tiempo compartido
Con el uso de la multiprogramación, el tratamiento por lotes puede llegar a ser bastante eficiente. Sin embargo, para muchas tareas, es conveniente suministrar un modo en que el usuario interactúe directamente con el computador. De hecho, para algunos trabajos, tales como el proceso de transacciones, este modo interactivo es fundamental.
Hoy en día, los requisitos de un servicio de computación interactiva pueden y suelen llevarse a cabo con el empleo de un computador dedicada. Esta opción no estaba disponible en los años 60, cuando la mayoría de los computadores eran grandes y costosas. En su lugar, se desarrollaron las técnicas de tiempo compartido.
Al igual que la multiprogramación permite al procesador manejar varias tareas por lotes al mismo tiempo, la multiprogramación puede también utilizarse para manejar varias tareas in-teractivas. En este último caso, la técnica se conoce como tiempo compartido, porque refleja el hecho de que el tiempo del procesador es compartido entre los diversos usuarios. La técnica básica de un sistema de tiempo compartido es tener a varios usuarios utilizando simultáneamente el sistema mediante terminales, mientras que el sistema operativo intercala la ejecución de cada programa de usuario en ráfagas cortas de cómputo o cuantos (quantum). De esta manera, si hay n usuarios que solicitan servicio a la vez, cada usuario sólo dispondrá, en promedio, de Un de la atención efectiva del computador, sin contar con la sobrecarga del sistema operativo. Sin embargo, dado el tiempo de reacción relativamente lento que tiene el ser humano, el tiempo de respuesta en un sistema correctamente diseñado debería ser comparable al de un computador dedicada.
Tanto la multiprogramación por lotes como el tiempo compartido utilizan multiprogramación.
Uno de los primeros sistemas de tiempo compartido que se desarrollaron fue el Sistema Compatible de Tiempo Compartido (CTSS, Compatible Time-Sharing System) [CORB62, CORB63], desarrollado en el MIT por un grupo conocido como Proyecto MAC (Machine-Aided Cognition, Multiple-Access Computers)3. El sistema fue desarrollado primero para una IBM 709 en 1961 y luego pasado a una IBM 7094.
Comparado con sistemas posteriores, el CTSS era bastante primitivo y su funcionamiento básico es fácil de explicar. El sistema se ejecutaba en una máquina con una memoria de 32K palabras de 36 bits, con un monitor residente que consumía 5K del total. Cuando había que asignar el control a un usuario interactivo, el programa del usuario y los datos eran cargados en las restantes 27K de la memoria principal. Un reloj del sistema generaba interrupciones a razón de aproximadamente una cada 0,2 segundos (sg). En cada interrupción de reloj, el sistema operativo se adueñaba del control y le podía asignar el procesador a otro usuario. De esta manera, a intervalos regulares, el usuario en curso era expulsado y se cargaba otro usuario en su lugar. Para conservar el estado del usuario anterior, para su reanudación posterior, los programas del usuario anterior y sus datos eran escritos en el disco antes de leer los programas del nuevo usuario y sus datos. En consecuencia, el espacio de memoria del usuario anterior debía ser restaurado cuando le llegara de nuevo su tumo.
Para minimizar el tráfico en el disco, la memoria del usuario se escribía a disco sólo cuando el nuevo programa a cargar podía sobrescribirla. Este principio se ilustra en la figura. Supóngase que hay cuatro usuarios interactivos con los siguientes requisitos de memoria:
Al principio, el monitor carga el TRABAJOl y le transfiere el control (figura a). Pos-teriormente, el monitor decide transferir el control al TRABAJ02. Puesto que el TRABAJ02 requiere más memoria que el TRABAJOl, éste debe sacarse primero, para luego cargar el TRABAJ02 (figura b). A continuación, se carga el TRABAJO3 para ser ejecutado. Sin embargo, como el TRABAJO3 es más pequeño que el TRABAJ02, entonces una parte del TRABAJ02 puede quedarse en la memoria, lo que reduce el tiempo de escritura en el disco (figura c). Más tarde, el monitor decide transferir de nuevo el control al TRABAJOl. Una parte adicional del TRABAJ02 debe sacarse cuando el TRABAJOl se cargue de nuevo a memoria (figura d). Cuando se cargue el TRABAJ04, parte del TRABAJOl y de la parte remanente del TRABAJO2 se retienen en memoria (figura e). En este punto, tanto si el TRABAJOl como el TRABAJO2 son activados, sólo se necesita una carga parcial. En este ejemplo es el TRABAJ02 el que se ejecuta a continuación. Esto exige que se saquen el TRABAJ04 y la parte remanente que estaba residente del TRABAJOl, para que se pueda leer la parte que falta del TRABAJ02.

El enfoque del CTSS era muy primitivo, si se compara con los sistemas actuales de tiempo compartido, pero funcionaba. Era extremadamente simple, lo que minimizaba el tamaño del monitor. Como un trabajo siempre se cargaba en las mismas posiciones de memoria, no había necesidad de utilizar técnicas de reubicación durante la carga (que se discutirán más adelante). La técnica de escribir en el disco sólo cuándo era necesario minimizaba la actividad con el disco. Ejecutado sobre una 7094, el CTSS daba soporte a un máximo de 32 usuarios.
El tiempo compartido y la multiprogramación plantean una multitud de problemas nuevos para el sistema operativo. Si hay varios trabajos en memoria, entonces deben protegerse de injerencias unos de otros, como, por ejemplo, que uno modifique los datos de otro. Con varios usuarios interactivos, el sistema de archivos debe protegerse de forma que sólo los usuarios autorizados puedan tener acceso a un archivo en particular. La contención de recursos tales como la impresora y los dispositivos de almacenamiento masivo debe estar controlada.
Sistemas para Redes Multiusuarios
Es todo lo contrario a monousuario; y en esta categoría se encuentran todos los sistemas que cumplen simultáneamente las necesidades de dos o más usuarios, que comparten mismos recursos. Este tipo de sistemas se emplean especialmente en redes.
En otras palabras consiste en el fraccionamiento del tiempo (timesharing).
Al igual que un equipo no puede trabajar sin un sistema operativo, una red de equipos no puede funcionar sin un sistema operativo de red. Si no se dispone de ningún sistema operativo de red, los equipos no pueden compartir recursos y los usuarios no pueden utilizar estos recursos.
Dependiendo del fabricante del sistema operativo de red, tenemos que el software de red para un equipo personal se puede añadir al propio sistema operativo del equipo o integrarse con él.
NetWare de Novell es el ejemplo más familiar y famoso de sistema operativo de red donde el software de red del equipo cliente se incorpora en el sistema operativo del equipo. El equipo personal necesita ambos sistema operativos para gestionar conjuntamente las funciones de red y las funciones individuales.
El software del sistema operativo de red se integra en un número importante de sistemas operativos conocidos, incluyendo Windows 2000 Server/Professional, Windows NT Server/Workstation, Windows 95/98/ME y Apple Talk.
Cada configuración (sistemas operativos de red y del equipo separados, o sistema operativo combinando las funciones de ambos) tiene sus ventajas e inconvenientes. Por tanto, nuestro trabajo como especialistas en redes es determinar la configuración que mejor se adapte a las necesidades de nuestra red.
Multitarea
Un sistema operativo multitarea, como su nombre indica, proporciona el medio que permite a un equipo procesar más de una tarea a la vez. Un sistema operativo multitarea real puede ejecutar tantas tareas como procesadores tenga. Si el número de tareas es superior al número de procesadores, el equipo debe ordenar los procesadores disponibles para dedicar una cierta cantidad de tiempo a cada tarea, alternándolos hasta que se completen las citadas tareas. Con este sistema, el equipo parece que está trabajando sobre varias tareas a la vez.