Introducción a los Sistemas Operativos: ¿Qué son los SO? Los SO son el corazón de toda computadora. El mismo proporciona servicios a usuarios y programadores que permiten utilizar una computadora sin tener que tratar con los comandos de hardware de bajo nivel difíciles de usar. Proporciona interfaces relativamente uniformes para acceder a la amplia variedad de dispositivos con los que interactúa una computadora. Además, la mayoría de los SO modernos proporcionan interfaces gráficas de usuario (GUI, Graphical User Interfaces). ¿Qué debe hacer un SO? ● Proporcionar una interfaz de alto nivel del hardware al usuario y a los programas. ● Administrar los recursos físicos (hardware, memoria principal, procesador, E/S, redes, comunicaciones) y lógicos (archivos, directorio, semáforos) de la computadora. El desfasaje o a sincronicidad se puede definir informalmente como la ocurrencia de eventos al azar o en momentos inesperados. Vista del Usuario contra la del Sistema en un SO: Para un SO las dos perspectivas más importantes son la vista del usuario y la vista del sistema. La vista del usuario consiste a cómo los usuarios o los programas utilizan el SO, por ejemplo, la forma en que un programa lee la pulsación de una tecla. A la vista del sistema concierne la forma en que el software del SO ejecuta realmente la acción requerida. A todo SO lo podemos ver de dos niveles, nivel de usuario (usuario final y programadores de aplicaciones) y nivel de sistema (programadores de sistemas y administradores de sistemas). Vista de los Usuarios y tipos de Usuarios: Hay que distinguir entre los usuarios finales, los programadores de aplicaciones, los programadores de sistema y los administradores del sistema. ● Usuarios de Aplicaciones (o usuarios finales): este grupo nos incluye a todos, gente que usa o ejecuta programas de aplicación o del sistema. Como usuarios esperamos una respuesta rápida y confiable. ● Programadores de Aplicaciones: este grupo incluye a quienes escriben programas de aplicaciones, como procesadores de palabras o sistemas de correo electrónico. Los programadores son muy exigentes con el SO. Las facilidades con que cuenta el SO son la vista de los programadores acerca del SO, y se denomina interfaz de programación de aplicaciones (API). Los programadores también desean que el software que desarrollan sea fácilmente transferible a otras plataformas. ● Programadores de Sistemas: se trata de quienes escriben software estrechamente relacionado con el SO. Necesitan comprender en detalle el funcionamiento interno del SO. Requieren acceder a estructuras de datos especiales en el SO o a las llamadas privilegiadas del sistema. ● Administradores del Sistema: este grupo incluye a las personas que gestionan facilidades de la computadora, y por lo tanto son responsables de instalar y actualizar el SO, así como otros programas y facilidades del sistema. También son responsables de crear y mantener las cuentas de los usuarios, así como de proteger el sistema. Deben comprender cómo el SO interactúa con otros programas y utilidades. Vista del Sistema: La vista del sistema se refiere a cómo el SO proporciona realmente los servicios. En otras palabras, se refiere a los trabajos internos del SO. Esta vista es menos común, que sólo les incumbe a los diseñadores y los implementadores del SO. Esta información a menudo es considerada secreta por las compañías que producen y venden SO, en caso contrario, estos sistemas se denominan sistemas de fuente abierta. Ejemplo del movimiento del mouse: ( No es importante) Aunque el movimiento del cursor de un mouse sobre una pantalla parece directo, ilustra las muchas vistas de un SO. Cuando el dispositivo apuntador se mueve, genera un evento de hardware denominado interrupción, que manipula el SO. El SO observa los movimientos del mouse en términos de algunas unidades específicas del hardware, es decir, las lecturas son en número de pulsos generados, en lugar de serlo en milímetros o pulgadas. Esta es la visión de bajo nivel del sistema. El controlador del dispositivo del mouse lee la información de bajo nivel del movimiento del ratón y otra parte del SO la interpreta, de modo que pueda ser convertida en una visión de nivel superior del sistema, como coordenadas en la pantalla que reflejan los movimientos del ratón. En el “otro lado” la vista del usuario es que el cursor se desplaza de manera continua sobre la pantalla. Otro ejemplo para vista del sistema: copiar de un CD a Disco 1. Comprobar que el archivo esté en el CD. 2. Ver si el archivo existe en el disco rígido. 3. Crear el nombre de archivo en el directorio 4. Buscar espacio libre en el disco para el archivo. 5. Leer los sectores de datos del CD. 6. Escribir los sectores de datos en el disco. 7. Actualizar la entrada de directorio en el disco 8. Actualizar la información de espacio libre en disco 9. Ejecutar todo esto en segundos. El SO depende de quien lo use y para que se usa BIOS (sistema básico de E/S): el BIOS abstrae el hardware, gestiona dispositivos comunes, como teclados, video básico y el reloj del sistema. Recursos gestionados por el SO: (Orden Jerárquico) Un papel fundamental del SO es la gestión de los recursos del sistema: ● CPU: el SO necesita planear cuál proceso ejecutar en la CPU en cualquier instante. En sistemas monotarea sólo un proceso reside en memoria en cada instante, pero en un sistema multitarea la gestión es más complicada ya que hay más procesos en la memoria, así que deben utilizarse estrategias más complejas para asignarle un tiempo a cada proceso en la CPU eficientemente. ● Memoria Principal y Caches: el SO necesita asignar espacio de memoria a un proceso antes de poder ejecutarlo. El código ejecutable de un programa suele almacenarse en el disco duro. Cuando un usuario o un programa desea ejecutar un programa que se encuentra en un disco, el SO debe localizar el archivo de código del programa y asignar suficiente espacio de memoria para mantener una parte inicial del programa. Debido a que muchos programas son bastante grandes, el SO debe cargar solo parte del programa desde el disco. ● Almacenamiento Secundario: este suele ser el disco duro, la mayoría de los archivos de código y los archivos de datos están almacenados en el disco duro hasta que hay una petición para cargar algunas partes de estos en la memoria principal. ● Dispositivos de E/S: el SO incluye módulos denominados controladores de dispositivos que vigilan el acceso a estos dispositivos. Estos manipulan la interacción a bajo nivel con el hardware, y presenta una vista de nivel superior de dispositivos de E/S al resto del SO. Debido a que hay muchos tipos de dispositivos de E/S, y a que los usuarios a menudo agregan nuevos a sus sistemas, los SO modernos cuentan con la capacidad de detectar nuevo hardware e instalar dinámicamente los controladores de dispositivos idóneos. ● Sistemas de Archivos: uno de los recursos de nivel superior que gestiona el SO más importantes es el sistema de archivos . Este sistema es un módulo del SO que proporciona una interfaz de nivel superior que permite que los usuarios y los programas creen, borren, modifiquen, abran, organicen, protejan archivos y accedan a estos usando diversas operaciones de archivos. ● Interfaces de Usuarios: esto incluye la funcionalidad para crear y gestionar ventanas en la pantalla de una computadora a fin de permitir que los usuarios interactúen con el sistema. Al tener este componente, el usuarios puede acceder a varios recursos en forma uniforme. ● Acceso a Redes: este recurso del SO permite que los usuarios y programas accedan a otros servicios y dispositivos en una red de computadores. Un SO es capaz de proporcionar funcionalidad tanto de bajo nivel como de alto nivel para el acceso a redes. ● Suministros de Protección y Seguridad: el SO también cuenta con mecanismos para proteger los diversos recursos de algún acceso no autorizado. Estos mecanismos de protección y seguridad hacen que el usuario no le cause daño a la máquina. Componentes de un SO: Los módulos proporcionan funciones a las que acceden usuarios y programas del sistema, así como los otros módulos del SO. Los tipos de interacción dependen de la arquitectura particular usada para implementar el SO. Por ejemplo: ● Arquitectura por capas ● Arquitectura orientada a objetos: cada módulo está implementado con uno o más objetos con servicios, y cualquier objeto puede invocar los servicios proporcionados por otro. ● Arquitectura monolítica Concepto de Proceso: Para cada acción que desee realizar un usuario en su computadora se crea un proceso. Un proceso, es un programa más su contexto (valor de las variables, los archivos que puede tener abierto, los punteros de los archivos, etc.). Sin embargo, un proceso no necesariamente está en ejecución todo el tiempo durante su existencia. Un programa desde que se ejecuta hasta que termina tiene diferentes estados. Hay modelos con diferentes números de estados, en este caso hay cinco. Al principio está en el estado nuevo , buscando los recursos necesarios para ejecutarse y cargarlos en memoria. Una vez que ya tengo todos los recursos asignados (menos la CPU), pasa al estado listo . Luego pasa al estado ejecutarse o correrse , hasta que termine, haga una llamada al sistema, o hasta que sea interrumpido. Luego pasa a un estado finalizado mientras el SO cierra todos los recursos que había recolectado. Ahora, no todos los programas empiezan y terminan en una pasada, puede ser que tengan que esperar a que el SO haga algo por medio de llamadas al sistema, también conocido como instrucción trampa, el programa deja de correr, se guarda el estado en memoria (pasa al estado espera o bloqueado , hasta que el SO haga lo que tenga que hacer) y se carga el SO para satisfacer esa llamada, luego que pasa eso el proceso vuelve a estado listo. Estas llamadas al sistema están documentadas por una API. Información del Proceso: Para seguir el camino del proceso, el SO suele asignarle un identificador único de proceso ( o ID del proceso ) . También crea una estructura de datos denominada Bloque de Control de Procesos (o BCP ) . En el BCP como mínimo guardan: ● Un identificador Único del Proceso (ID del proceso) ● Información de Prioridad (que tan importante es este proceso) ● Estado del Procesador. ● Puntero a las estructuras de datos ● Punteros a los archivos que tenga este proceso (que archivos tiene abiertos) ● Información de seguridad y autorización. ● Otros datos que dependen de cada SO particular. Tipos de procesos y modos de ejecución: Los procesos pueden clasificarse en varios tipos: 1. Procesos del usuario: procesos que se encuentran ejecutando programas de aplicación en representación de un usuario. 2. Procesos del sistema: son otros programas de aplicación que efectúan un servicio del sistema común en lugar de un servicio específico de usuario final. Procesos del SO: también se les conoce como demonios , y se trata de procesos que se encuentran ejecutando servicios y funciones del SO. Por ejemplo, gestión de la memoria, planificación de procesos, control de dispositivos, etc. Casi todos los procesadores cuentan con dos modos de ejecución para los procesos: el modo privilegiado (o kernel) y el modo usuario . Los procesos del núcleo del SO por lo regular se ejecutan en modo privilegiado, permitiéndoles ejecutar todos los tipos de operaciones de hardware y acceder a todos los dispositivos de memoria y de E/S. Otros procesos se ejecutan en el modo del usuario, que le prohíbe ejecutar algunos comandos, como los comandos de E/S de bajo nivel. El modo del usuario también introduce el mecanismo de hardware de protección de la memoria, de modo que un proceso solo puede acceder a la memoria dentro de su espacio de memoria predefinido. Esto protege el resto de la memoria de acceso erróneo o malicioso a su espacio de la memoria que puede dañar sus datos o el código del programa. Tipos de SO: Hay muchos tipos de SO, los siguientes son seis tipos comunes: ● Monotarea - Monousuario: este SO ejecuta un solo programa la vez y solo para un usuario a la vez. Los primeros SO era de este tipo, así como los SO de las primeras computadores personales (como CP/M o MS-DOS). ● Multitarea - Monousuario: un SO así controla la ejecución simultánea de múltiples procesos. Por lo tanto, debe contar con un componente de planificación de la CPU que escoja cuales de los procesos listos ejecutar a continuación. Al tener varios procesos listos en la memoria para ejecutar, la CPU puede cambiar de la ejecución de un proceso a la ejecución de otro esto se denomina cambiar de contexto . Pero hay un costo elevado para hacer esto, es necesario guardar todo el estado del proceso que está siendo ejecutado, de modo que sea posible restaurarlo una vez que el proceso se reanude más tarde. ● De tiempo compartido: el tiempo de la computadora era “compartido” por los múltiples usuarios simultáneos. A medida que el precio del hardware y de los procesadores se reducía en forma dramática, la necesidad por tiempo compartido declinaba. ● De red: hoy en día las computadoras cuentan con una funcionalidad extra en la cual están conectadas permanentemente a una red o están equipadas de modo que puedan conectarse y desconectarse de algún tipo de red. Esta funcionalidad puede clasificarse en dos niveles principales: ○ Servicios de bajo nivel: el SO incluye una funcionalidad para establecer conexiones a redes, para enviar y recibir mensajes entre las máquinas conectadas. ○ Servicios de alto nivel: los usuarios desean conectarse a otras máquinas para buscar información, descargar archivos o programas, o para acceder a bases de datos. (los routers o access points) ● SO distribuidos: estos pueden permitir que un usuario que inicio sesión en la máquina de un cliente acceda en forma transparente a todos los servicios y archivos posibles a los que está autorizado sin siquiera saber donde reside. (la nube) ● De tiempo real: hay dos tipos: ○ Plazos duros: en caso de no completarse la tarea en el tiempo dado, pueden haber consecuencias catastróficas para el sistema. ○ Plazos blandos: debe completarse en el tiempo dado, pero en el caso de no hacerse no hay consecuencias. ● Para Dispositivos Móviles: (Teléfonos) Enfoques Arquitectónicos para construir un SO: ● Enfoque Monolítico: los primeros SO se escribieron como un programa único. A medida que los sistemas fueron creciendo, aumentaron los errores y eran difíciles de mantener, por lo que se debió encontrar otro enfoque más modular. ● Enfoque Micronucleo o Microkernel: en el micronucleo solo se incluye funcionalidad básica. Específicamente, el único código en estos módulos debe ejecutarse en modo supervisor, porque usa recursos privilegiados, como instrucciones protegidas, o accede a la memoria que no está en el espacio del núcleo. El resto de las funciones del SO se sigue ejecutando en modo de usuarios. El código que se ejecuta en el modo kernel literalmente puede hacer cualquier cosa, por lo que un error en este código puede ocasionar más daño del que se ejecuta en el modo de usuario. Entonces los beneficios de este enfoque surgen del hecho que la cantidad de código que se ejecuta en el modo supervisor es más pequeña, lo cual lo robustece más. ● Enfoque por Capas: el SO se divide en módulos que están limitadas a una función específica, como la planificación del procesador o gestión de la memoria. Los módulos están agrupados en capas de abstracción creciente (cada capa proporciona una vista más abstracta del sistema). Los SO más modernos están construidos con base en una arquitectura por capas. ● Enfoque Cliente-Servidor Enfoque Monolítico vs Micronúcleo: Arquitectura en Capas: SO Monotarea o Monoproceso: Planificación de Procesos (Planificación de la CPU); Cuando un proceso se coloca en el estado listo, es necesario decidir cuándo debe ejecutarse en relación con los procesos que ya están en el estado listo. Esta decisión la toma un módulo del SO denominado planificador a corto plazo . Hay varias formas de otorgarle la CPU a un proceso: ● (FCFS: First Come, First Served): es el método más simple y utilizado por muchos SO, consiste en ejecutar un programa primero en entrar, primero en salir (una cola FIFO, first-in, first-out). Sus ventajas son que es fácil de implementar, fácil de comprender por parte de diseñadores y usuarios. Por último es el más justo ya que no favorece a un proceso por sobre otro, y económico en recursos. ● Por Prioridades (le va a dar la CPU al más importante): en un algoritmo por prioridad damos precedencia a cada proceso. Siempre que permitimos que algunos trabajos tengan prioridad mayor sobre otros se presenta un problema; es posible que los procesos con más prioridad están postergando un proceso de baja prioridad hasta el punto en que este último jamás sea ejecutado. Este problema se denomina inanición . En general, para solucionar este problema monitoreamos los procesos que se han postergado, y siempre que un proceso se pospone demasiadas veces, simplemente elevamos temporalmente su prioridad. En algún momento este proceso se ejecutara y luego hacemos descender la prioridad a donde estaba originalmente. ● Garantizada: a un proceso se le asigna una parte de tiempo de la CPU, lo utilice o no. El problema es que desperdicia mucha CPU, y tampoco se sabe si va a alcanzar este tiempo para otros procesos. ● SRTF (shortest runtime first): esto se traduce a, el siguiente trabajo más corto. Simplemente selecciona el siguiente trabajo a ejecutar tal que se ejecute en la menor cantidad de tiempo posible. No se suele usar este ya que hay que saber el tiempo que va a llevar ejecutar cada proceso. ● HRRN (highest response ratio next): se traduce a, siguiente mayor tasa de respuesta. Tiene en cuenta los programas más interactivos, para darles más prioridad. Esta variante se usa principalmente porque disminuye la probabilidad de inanición. Planificación de la memoria principal: Es necesario administrar la memoria principal porque es un recurso escaso y caro, además para: ● Cargar la mayor cantidad de procesos que hagan falta. ● Llevar registro de que está libre, asignado y a quien, en casos si no hay suficiente memoria, le puede quitar memoria a algún programa para darle a otro más importante. ● Brindar de manera transparente la memoria que requieren las aplicaciones. El objetivo básico de la gestión de la memoria es permitir la ejecución de la mayor cantidad de procesos posibles. Creación de programas: 1. Escribir código fuente 2. Compilación/traducción 3. Enlazamos este módulo con módulos semejantes creados por separado, ya sea en estático o en dinámico. 4. Carga en Memoria (lee las variables, tamaños, recursos, todo del ejecutable y se fija cual es la primera instrucción) 5. Ejecución Un solo proceso: En el entorno del CP/M, el SO residía en la parte superior de la memoria. Los programas de aplicación empezaban en la ubicación 100. Desafortunadamente, a medida que el SO crecía podía volverse tan grande que un SO actualizado podía utilizar la memoria que necesitaba un programa que estaba ejecutándose bien antes de la actualización del SO. En la siguiente figura se ve la arquitectura típica de uno de los primeros SO para una computadora que sólo ejecutaba un proceso único. Estos sistemas siguen presentando el problema de que, si el SO crece, los programas deben ligarse con nuevas direcciones. La solución a este problema era modificar de alguna manera la función del registro base. Reubicación dinámica: Cambia el nombre, lo que antes se llamaba registro base, ahora se denomina registro de reubicación, como se muestra en la figura siguiente. Ahora el programa no tenía que volver a ligarse cada vez que el SO se actualizaba o crecia, puesto que toda referencia a la memoria se ubicaba de manera automática a medida que se ejecutaba el programa. Espacio RAM físico vs RAM lógico: Esta nueva función de reubicación introduce un concepto importante: la diferencia entre el espacio de dirección lógico y el espacio de dirección físico. Originalmente, cuando se compilaba un programa, se creaba un programa que había que cargar en la RAM en la dirección que se le asignaba. El programa se compilaba refiriendo un rango de direcciones que corresponden uno a uno con las direcciones de memoria física real. En realidad había dos espacios de direcciones, el primer espacio de direcciones es el conjunto de direcciones que genera la CPU a medida que se ejecuta el programa, este espacio se denomina espacio de direcciones lógicas. El programa ejecutable se cargaba en la memoria primaria. El conjunto de direcciones usado para acceder a esta memoria se denomina espacio de direcciones físicas. Con el nuevo concepto de reubicación dinámica, se hace evidente que el espacio de direcciones lógicas y el espacio de direcciones físicas del programa son diferentes. Super Posiciones (Overlays): A menudo los programadores requieren agregar funciones a programas que pueden ejecutarse en memorias pequeñas. Es bastante común tener un programa integrado por tres partes: una fase de inicio, un bucle principal y una fase final de reporte. Estas partes de un programa no necesitan estar en la memoria al mismo tiempo, de modo que se superponen entre si en la memoria. Intercambio es espacio (Swapping): Esto consiste en mantener varios programas en ejecución al intercambiarlos, lo que funciona como se muestra en la siguiente figura (muestra el programa A en ejecución en la memoria principal). Archivos: Los sistemas de archivos suelen tener diseños por capas, donde cada una proporciona servicios a la capa que está arriba de ella. Hay dos cuestiones que son claras, la capa superior, la API, es una abstracción del concepto de archivos y la capa inferior interactúa directamente con el hardware. Directorios: El SO requiere contar con algún tipo de índice de los archivos que el programa puede buscar, estos índices se denominan directorios (folders o carpetas). Los directorios deben almacenar el nombre del archivo, pero además otros datos sobre el mismo. La información sobre el archivo que no forma parte de los datos del mismo se denomina metadatos del archivo. Estructura lógica: Hay varias estructuras lógicas diferentes que pueden usarse a fin de almacenar una estructura de directorio para un sistema de archivos. De un solo nivel: la forma de organizar lógicamente el directorio en un disco depende del tamaño de este. Estructura de árbol: un desarrollo importante en la organización de la estructura lógica de los directorios del disco fue permitir directorios múltiples. El truco principal consistió en permitir simplemente que los directorios se refieran a otros, además de referirse a otros archivos. Con esta organización jerárquica de directorio es posible dividir los archivos en varias categorías. En maquinas con mas de un usuario, podemos asignar a cada usuario un directorio “de inicio”, que contiene todos sus archivos de datos en subdirectorios. Grafos acíclicos: Con un solo directorio estructurado como un árbol, estamos en un problema sobre cómo clasificar algún archivo. Además, a veces no podemos recordar en qué directorio decidimos colocarlo. Una solución que se usa algunas veces para resolver este dilema consiste en permitir que los directorios formen grafos acíclicos dirigidos . Estos es una entrada que no apunta directamente a un archivo, sino a otra entrada del directorio. Métodos de acceso: Los programas necesitan diferentes maneras de acceder al contenido del archivo: ● Acceso secuencial: para el procesamiento secuencial en almacenamiento de disco, el SO debe contar con alguna definición del tamaño del registro para cada archivo y luego debe seguir la pista de la posición actual para cada aplicación que tuviera abierto el archivo. Además, el SO incrementa el apuntador de registro actual cada vez que hay una lectura o una escritura. ● Acceso aleatorio: en este modelo, la aplicación indica al SO que registró en el archivo necesita y el SO se mueve directamente a ese registro para leer o escribir. Esto requiere asignación simple de un valor clave al número de registro. Cuando la aplicación tiene acceso aleatorio a un archivo, esto coloca el apuntador de registro en el registro siguiente, ahora la aplicación puede emitir una operación read next y el SO regresa el siguiente registro e incrementa el apuntador de registro actual. Por ejemplo, en una empresa pequeña podría simplemente asignar secuencialmente los números de empleado y usar el número de empleado como número de registro. ● Métodos de acceso de alto nivel: la mayor parte de los SO cuentan por lo menos con los dos métodos de acceso mencionados anteriormente. Algunos SO tienen uno o más métodos de acceso de nivel superior: ○ Acceso Indexado: El acceso aleatorio a veces no funciona para un archivo grande, ya que después de un tiempo, muchos registros se no serán utilizados, quedarán anticuados, etc. El resultado es que un archivo maestro con acceso aleatorio habrán muchos registros que ya no representan nada. Para esto se utiliza el método de acceso de alto nivel indexado. Tiene tres áreas, el área de datos primarios , donde se guardan los datos; el área de clave única o clave principal , que es un índice para el campo clave principal en el registro, y un área de clave secundaria, que es un índice para una variable diferente. A medida que se agregan registros al archivo, estos se escriben secuencialmente en el área de datos primarios. Sin embargo, para cada archivo escrito en el área de datos primarios, en el área de clave principal se escribe un registro adicional y en el área de clave secundaria se escribe otro registro. Un método de acceso así está próximo a ser una base de datos, pero es algo más simple. Estas tres áreas que se analizan pueden ser porciones de un archivo único o pueden almacenarse por separado como archivos ajenos. ○ Acceso hash: puede aplicarse la técnica hash a un campo para crear un valor clave aleatorio para tener acceso a un archivo de acceso aleatorio cuando no se usan todos los valores clave. ● Acceso en bruto (raw): en este caso, el SO no proporciona ninguna estructura de archivos, sino que reserva un área de disco donde las aplicaciones pueden proporcionar su propia estructura. Gestión de espacio libre: El SO almacenará los datos de los archivos y directorios de bloque del disco. Para ello debe saber cuáles bloques no han sido utilizados aún: Lista enlazada: hay bloques en una unidad de disco, el SO debe seguir la pista del primer bloque en la lista. Cada bloque contiene entonces un apuntador hacia el siguiente bloque libre. La lista no está en cualquier orden. Podemos empezar inicialmente con una lista ordenada, pero cuando una aplicación libera un bloque es necesario poder colocarlo en la parte frontal de la lista, de modo que no tengamos que preocuparnos por cambiar cualquier otro sector en el disco para apuntar a este nuevo bloque recientemente liberado. Tomamos el apuntador hacia el bloque que se encuentra en la cabeza de la lista y lo colocamos en el nuevo bloque liberado. Escribimos el sector del bloque que contiene el apuntador del siguiente bloque libre al disco y registramos el bloque recientemente liberado como el primer bloque en la lista. Un buen aspecto de este mecanismo es que el único espacio extra necesario es el apuntador único a la cabeza de la lista. Un mal aspecto es que resulta difícil asignar bloques de espacio contiguos. Listas enlazadas mejoradas: las listas enlazadas para trabajar mejor requieren contar con algún medio para que no tengamos que leer cada sector antes de usarlo. Hay varias maneras de hacer esto, dos comunes incluyen agrupamiento e indexación. Con la indexación almacenamos varios apuntadores de espacio libre en un solo bloque, este primer bloque se denomina bloque índice . Otro mecanismo es el agrupamiento, en esta técnica, el SO aprovecha todas las oportunidades para determinar que dos o más bloques en la cadena son adyacentes . En este caso, el primer bloque en este grupo contiene no solo un apuntador al siguiente bloque libre, sino que también una indicación de cuántos de los siguientes bloques en la lista son adyacentes entre si. Esto permite que el mecanismo coloque bloques contiguos más fácilmente. Pero también el primer bloque puede leerse y luego el resto de los bloques del grupo pueden manipularse sin necesidad de leer nuevamente el disco. Mapa de bits: Otro enfoque es contar con un mapa de bits en el que cada bloque en el sistema de archivos esté representado por un solo bit en una gran cadena. Con un mapa de bits es más fácil asignar múltiples bloques contiguos, basta con encontrar una cadena de bits contiguos del tamaño requerido. Este mecanismo ocupa más memoria que el de las listas enlazadas, ya que debemos mantener en memoria una porción del mapa de bits. Gestión de Espacio Ocupado: Asignación contigua: significa que los bloques fijados a un archivo tienen números en una secuencia estrictamente creciente por 1. Estos bloques no necesariamente comienzan en el límite de una pista. Este esquema de asignación de espacio de archivos presenta varias ventajas: para encontrar todos los datos se requiere muy poca información, basta con la dirección del sector del primer bloque y la longitud del archivo en los bloques. Un problema con la asignación contigua es que una vez que se ha asignado un archivo, puede ser difícil hacerlo más grande porque es probable que algún otro archivo sea asignado después del que queremos hacer más grande. Para evitar este programa, lo que se suele hacer es asignar más almacenamiento para el archivo que está siendo requerido por los datos. Esto se denomina fragmentación del programador . Esto desgraciadamente es desperdicio de almacenamiento, además, si hay suficiente espacio libre en el disco para asignar otra copia del archivo, la operación es bastante simple, aunque puede consumir tiempo si el archivo es grande. Si no hay suficiente espacio para la nueva copia, es necesario hacer un proceso tedioso, por lo tanto surgieron las extensiones . En este esquema, un archivo no está limitado a una asignación contigua única, la asignación inicial es un bloque contiguo, pero si esta lleno, en lugar de hacer una nueva copia, se efectúa la asignación secundaria, no necesariamente contigua a la asignación inicial. Hay varias instancias de desperdicio en el esquema de la asignación contigua. La primera es provocada por el hecho de que la porción más pequeña del espacio al que podemos tener acceso, es un sector. Este espacio sin usar provocado por la granularidad de la asignación se denomina fragmentación interna . Igualmente, un problema mayor es el de la fragmentación externa , este problema surge cuando estamos a punto de llenar el disco, a medida que vamos asignando archivos contiguos, tendemos a cortar el espacio libre porque sacamos una parte del espacio libre más grande. Finalmente los huecos que quedan se vuelven demasiado pequeños para la siguiente asignación. La solución al problema se denomina desfragmentación/compactación y es complicada, la idea básica es mover algunos archivos hacia huecos donde quepan dejando huecos más grandes para los archivos que queremos asignar. Asignación enlazada: este mecanismo es como una estructura de lista enlazada en memoria primaria, pero aquí los elementos vinculados siempre son del mismo tamaño: un bloque de disco. Cada bloque contiene la dirección del sector de inicio del siguiente bloque en el archivo. Un inconveniente del mecanismo enlazado es que en este vínculo se desperdicia una parte de cada bloque. Un archivo enlazado contiene un apuntador hacia el primer bloque del archivo y la longitud del archivo en bloques. El lado bueno es que con asignación enlazada no hay fragmentación del programador. Entrada/Salida: Hay diferentes categorias de E/S, que los SO tratan de maneras diferentes. Dispositivos: El SO debe tener en cuenta las características de los dispositivos: ● Acceso Aleatorio o secuencial: cuando hablamos de dispositivos de almacenamiento secundario, específicamente unidades de disco, estas unidades podemos tomarlas como si fueran de “acceso aleatorio”, sin embargo, esto no significa que el tiempo para tener acceso a los datos sea independiente de la ubicación de los mismos. ● Clases de Dispositivos: la mayoría de los SO dividen de manera amplia los dispositivos en tres clases: de bloques, de caracteres y de red. ○ Dispositivos de Bloque: un dispositivo de bloque lee o escribe un bloque a la vez. El tamaño de un bloque está determinado parcialmente por el hardware, pero también por los administradores del sistema, cuando se establece el sistema de archivos. Estos dispositivos a menudo tienen acceso aleatorio directamente a cualquier bloque en el dispositivo; es decir, en el bloque es posible leer o escribir en cualquier orden. A veces, algún software requiere acceso a estos dispositivos directamente en lugar de hacerlo mediante el empleo del sistema de archivos, a esto se le denomina E/S en bruto . ○ Dispositivos de Caracteres: estos dispositivos transfieren datos a razón de un solo byte a la vez. Incluyen por ejemplo, impresoras, ratones, teclados, etc. Atienden la mayor parte de operaciones básicas como los archivos en modo de bloques: apertura, cierre, lectura, escritura. Los dispositivos de caracteres no pueden atender la búsqueda hacia atrás. ○ Dispositivos de Red: estos dispositivos no se ajustan a la semántica tradicional de las operaciones con archivos. El problema es que las aplicaciones que están esperando datos de entrada desde una red nunca saben cuándo estarán disponibles los datos, o si es que lo estarán en algún momento. Es por esto que los dispositivos de red cuentan con una serie de interfaces. Tecnologías de E/S: El SO debe tener en cuenta las tecnologías de E/S: Buffers: cuando introducimos datos en un sistema informático, por lo general leemos de un dispositivo y escribimos en otro. En este caso usamos una técnica que se denomina almacenamiento en buffer . Un buffer es una porción de la memoria donde se almacena un registro que se usará en una operacional de E/S. Una razón por la cual puede usarse es si el usuario que escribe un documento produce un solo carácter a la vez, sin embargo, no podemos escribir un solo carácter en un disco, la unidad más pequeña de acceso es un sector. Entonces usamos un buffer para guardar los caracteres que el usuario escribió, hasta que haya suficientes para llenar un sector, luego escribimos el sector al disco y empezamos un nuevo sector. Esto funciona cuando la diferencia de velocidades entre los dispositivos es pequeña, en cambio, si estas velocidades difieren en un factor de tres o cuatro, hay que utilizar otra técnica denominada el doble almacenamiento en buffer. En esta técnica, se asignan dos buffers para el proceso, primero llenamos un buffer y luego iniciamos la operación para escribir en el dispositivo de salida. A medida que empezamos a escribir, comenzamos a llenar el segundo buffer para los datos de entrada. Para el momento en que el segundo buffer está lleno, la escritura del primero debe estar terminada y entonces podemos empezar a escribir en el segundo mientras comenzamos a llenar nuevamente el primero. Caches: esta técnica se utiliza tanto en hardware como en software. Su propósito es hacer parecer que una memoria mas grande, mas lenta pero más barata se desempeña a la misma velocidad que una memoria más pequeña, más rápida y por lo tanto, más costosa. Estas memorias funcionan porque los procesos en realidad no tienen acceso aleatorio a la memoria. En lugar de ello, operan según el principio de ubicación de referencia, el cual establece que es más probable hacer referencia a direcciones en la memoria que estén más próximas a las que ya se ha hecho referencia, que hacerlo a direcciones que no estén. El otro aspecto del principio del ubicación dice que una vez que un proceso ha emitido a una ubicación en la memoria es más probable que vuelva a dirigirse a ella de nuevo a que lo haga a otra ubicación aleatoria. Operaciones de Bloque: estas consisten en empacar varios registros lógicos en un bloque físico para escribir en un dispositivo; es algo semejante al almacenamiento en buffer. Esta técnica se usa porque los apuntadores al sistema de archivos no eran suficientemente grandes para direccionar todos los sectores en algun nueva unidad de disco, de modo que asignamos múltiples sectores al mismo tiempo. Organización Física del Disco: Sectores, Pistas, Cilindros y Cabezas: En la figura se ven dos platos de disco duro montados sobre un eje, de modo que pueden girar juntos. Cuatro brazos se extienden sobre los platos, cada uno contiene una cabeza magnética para lectura y escritura. Los brazos pueden desplazarse hacia adentro o hacia afuera; con los brazos estacionarios en cualquier posición, los platos giran de modo que un anillo de la superficie de un disco pasa por la cabeza. Ese anillo se denomina pista . Los cuatro brazos están conectados entre si, de modo que se mueven hacia dentro y hacia afuera como una unidad. Esto significa que hay cuatro pistas que la unidad puede leer sin mover los brazos, uno para cada cabeza y superficie. Este grupo de pistas se denomina cilindro . Una pista está dividida lógicamente en sectores . Los sectores son la unidad más pequeña de datos que una unidad de disco puede transferir. Este arreglo del hardware de la unidad de discos lleva el concepto de dirección de disco, que se puede especificar mediante el número del cilindro, de la cabeza y del sector, o direccionamiento CHS. Un disco con C cilindros, H cabezas y S sectores por pista tiene C x H x S sectores en total y normalmente puede almacenar C x H x S x 512 bytes. Zonas de Conteo de sectores y direccionamiento de sectores: Una unidad de disco gira a velocidad constante. La circunferencia de las pistas exteriores es más larga que la de las interiores, de modo que puede almacenarse más información en las pistas exteriores que en las interiores. Se usa una técnica para la sincronización denominada grabación por zona de bits . Esta técnica divide las pistas del disco en zonas de pistas de tamaño semejante y cambian la sincronización para las pistas en cada zona. Como resultado colocan más sectores en las pistas de las zonas exteriores y menos en las de las interiores. Velocidades: búsqueda, transferencia y almacenamiento en buffers Uno de los factores más importantes en el rendimiento del SO es el tiempo de búsqueda o tiempo de posicionamiento de la unidad de un disco duro. Es el tiempo que requiere la unidad para mover el montaje de la cabeza de una pista a otra. Organización Lógica del Disco: Particiones: Con los SO se proporcionó un programa de utilidad denominado FDISK que podía usarse para dividir el disco en particiones por separado. Crear particiones es una técnica útil para varias cosas, por ejemplo, si se quiere que una máquina contenga dos SO y que, aún así, permita que cada uno asuma que sólo él tiene el control sobre la unidad de disco. La información sobre la partición de un disco duro se almacena en una parte del primer sector físico del disco, sin importar como se establece la partición. Este sector se denomina sector de arranque o bloque de arranque del disco y contiene la tabla de particiones . Bloque de arranque: Cuando una PC se reinicia, normalmente trata de arrancar un SO desde uno o más dispositivos del sistema. CP/M: Un SO simple de proceso único Introducción a los monitores Los predecesores de los SO se denominaban monitores, y tenían capacidades muy limitadas. Los programas de aplicación se escribían en lenguaje máquina o ensamblador. No había ningún SO, si no que había un pequeño programa monitor que permitía que una aplicación realizará tareas comunes simples como: ● Emitir un carácter a un dispositivo como una pantalla de video o un teletipo. ● Obtener un carácter desde el teclado. ● Guardar el contenido de toda o parte de la memoria a un dispositivo de almacenamiento. ● Restaurar el contenido de la memoria desde un dispositivo de almacenamiento. ● Imprimir un carácter en la impresora. ¿Por qué el CP/M? ¿Cuál era la crisis de software? Como cada fabricante elaboraba programas de monitor de acuerdo a lo que creían que los programadores necesitaban, se hacía difícil elaborar programas portables, o sea que sean ejecutables en distintas computadoras. Esto condujo a la creación del CP/M (Control Program/Monitor), fue escrito para que los desarrolladores y usuarios posean una interfaz sencilla y estándar. Creado para microcomputadoras con base en los circuitos CPU Intel 8080&8085, por Gary Kindall. Componentes del CP/M Esto se logró mediante una capa de software llamado BIOS el que relacionaba software con el hardware, de esta manera el SO podia ser usado en otras computadoras, modificando levemente el BIOS de acuerdo al hardware utilizado. El corazón del SO se llama BDOS , el cual se encarga de llamar a los servicios más primitivos de la BIOS y es independiente del hardware utilizado. La última parte del sistema se conoce como CCP , es la interfaz de usuario encargada de ejecutar los comandos escritos por los usuarios. Características de un sistema de PC simple ( No muy importante) Los primeros PC constaban de una tarjeta madre de circuitos. La misma tenía una pastilla microprocesadora (CPU), algo de memoria RAM, una ROM que contenía el BIOS y varios circuitos integrados (CI) que unían todas las pastillas. La tarjeta madre contaba con “tarjetas” para insertar tarjetas de circuitos adicionales, como RAM adicional, disquetes. La entrada/salida se realizaba a través de un monitor de video y un teclado, conectados a la tarjeta madre. Algunas de las características de este tipo de sistema: 1. El tamaño de la memoria principal era demasiado limitado: Por eso el SO solo cargaba un programa por vez. Si una App no entraba en la memoria disponible, se usaba la técnica overlays (superposiciones) para sustituir la sección antigua con la nueva. 2. El formato de disco se estandarizó. Se fijaron el tamaño y el formato del bloque del disco tanto para disquetes como para discos duros. 3. La manipulación de interrupciones era prácticamente para dispositivos de E/S, puesto que solo se ejecutaba una App a la vez. Gestión de procesos: Monoproceso, el proceso se carga en la RAM empezando en la dirección 100H, si un programa era demasiado grande se utilizaba la técnica de overlays. Se les asigna espacio de pila en la memoria alta antes del S.O. El proceso se ejecuta de principio a fin, si requiere E/S el procesador permanece ocioso hasta finalizar la operación (E/S programada). En este SO simple, la gestión de procesos era limitada, ya que sólo está en ejecución un programa a la vez. Creación y ejecución de un programa de aplicación Un programa se escribe, se compila y luego se vincula con las rutinas de la biblioteca usando un editor de enlace . El resultado es un archivo imagen de un programa listo para ser cargado en la memoria y ejecutado (se le llama programa ejecutable). Para que empiece a correr, debe cargarse en la memoria su código ejecutable. Este proceso lo hace el CCP, este hace su trabajo haciendo solo llamadas al BDOS, nunca llama directamente al BIOS. Cuando se introduce un nombre al CCP, si se trata del nombre de un comando integrado se ejecuta ese comando. Si el nombre no es el de un comando integrado , el CCP intenta encontrar un archivo ejecutable en el disco con ese nombre. Si existe uno, el contenido de ese archivo se carga a la memoria y el programa empieza a correr. El proceso se ejecuta desde el principio hasta el final. Si requiere E/S, la CPU permanece inactiva hasta que se completa la E/S requerida. En otros SO, el componente semejante al CCP algunas veces se denomina shell o intérprete de comandos. Un usuario puede invocar directamente a los comandos del CCP al escribir un comando del CCP o el nombre de un archivo con el ejecutable del programa. Gestión de la memoria Al tener una memoria principal muy limitada, se decidió que sólo so cargará un programa a la vez en memoria. El SO, al ser pequeño siempre se encontraba en la parte alta de la memoria. Si un programa no cabía en memoria, se debería escribir la aplicación para que entrara, cuando se necesita una nueva sección se utiliza la técnica de overlays para sustituir la antigua por la nueva. El formato de disco se estandarizó, por lo tanto se fijaron el tamaño y el formato del bloque de disco, lo que condujo a una estandarización del sistema de archivos. Las interrupciones sólo se utilizaban para dispositivos de E/S ya que no era posible ejecutar más de una aplicación a la vez, además de no necesitar una planificación de la CPU. El CCP carga los programas en la memoria, dividiéndolos en 2 partes: el código ejecutable y los datos del programa. En general, los programas utilizan una pila para sus variables temporales, esta se encuentra en la parte alta de la memoria por debajo del SO. El software que copia estas dos partes en la memoria se denomina cargador. Los programas normales se cargan en la RAM, empezando en la dirección 0100 Hex. Al contar con una dirección fija, facilita a los compiladores y enlaces crear ejecutables. No se cuenta con un sistema de protección para evitar que la pila sobreescriba al programa. Una cabecera del programa estaba ubicada en la memoria inmediatamente antes del código del ejecutable. Esta contiene apuntadores a direcciones de la memoria donde estaban ubicados la pila y datos fijos, también suministraba argumentos al programa. El SO estaba localizado en la parte más elevada en la memoria porque no todos los sistemas CP/M tenían la misma cantidad de memoria (podrían tener 32, 48 o 64 k). Así el SO se configuraba para ocupar las ubicaciones más elevadas en la memoria, dejando una dirección fija para cargar programas. Si el SO se volvía más grande, podía empezar en una dirección más baja en la memoria, pero sin obligar a ningún programa a cambiar de dirección. Gestión de Entrada/Salida La manipulación de E/S era muy limitada,el BIOS estaba especializado para cada tipo de teclado. Se requerían funciones simples como presionar caracteres, mostrar caracteres en pantalla, o imprimir. Había un gran debate entre portabilidad vs flexibilidad, ya que saltándose el BIOS y accediendo directamente al BDOS se obtiene flexibilidad adicional, a costa de perder la portabilidad hacia otros equipos diferentes. Entrada desde el teclado: Portabilidad vs Flexibilidad Debido a que los teclados hicieron su aparición en varios tipos el BIOS estaba especializado para cada tipo de teclado, aunque proporcionaba una misma interfaz al resto del SO. Luego, el BDOS usaría las funciones del BIOS para crear una interfaz más simple para el teclado. Estas funciones para el teclado eran: 1. Leer un carácter del teclado 2. Comprobar si se había oprimido una tecla Salida desde el monitor de video: movilidad vs funcionalidad vs desempeño La pantalla o monitor de video planteaba problemas más importantes . Primero, las funciones disponibles a través de las funciones de interfaz del BDOS y el BIOS eran limitadas. Había muchas características de sistemas de video que no era posible usar directamente por las llamadas simples al sistema del SO. Segundo, la salida desde la pantalla usando el BDOS era muy lenta. Muchas aplicaciones podían escribir caracteres directamente en la memoria de la pantalla y tener acceso directamente al hardware del controlador de video. La razón más importante para evitar el BDOS era mejorar el desempeño de la aplicación. Escribir directamente en la memoria de video proporcionaba no sólo más funcionalidad sino que también era mucho más rápido que ir a través de una llamada al sistema del SO. Sistema de archivos Uno de los principales servicios que proporcionaba el SO era un sistema de archivos estándar y portátil. Una pista tenía 26 sectores, el primer sector denominado con el 1, y el último con 26, cada sector contiene 128 bytes de datos. El sistema de disco comprendía la unidad de disco y el controlador de disco . La unidad era la que contenía almacenados los datos y el controlador de disco solía estar integrado en la Mother, y este se encargaba de leer o escribir en uno o varios sectores en una pista. Debe controlar que no se haya leído o ido a una pista equivocada. Un disco tenía 512 bytes de datos. Gestión de Archivos: El SO contaba con un sistema de archivos sencillo integrado en la parte superior del BIOS. Una parte de los archivos que pueden almacenarse en un disco contiene el código binario del SO en sí. Cada disco tiene un directorio que almacena información acerca de los archivos almacenados; sus tamaños, su ubicación física, donde están almacenados. Cada disco físico se divide en tres áreas: 01.Área de arranque del disco: pequeña, simple, contiene el binario del SO para arrancar la PC. Cuando se reinicia la PC se ejecuta un pequeño programa en la ROM que copia la imagen ejecutable del SO desde el disco hasta la memoria. 02.Área del directorio de archivos: contiene información sobre cada archivo almacenado. Tamaño fijo y se registra en una tabla en el BIOS. Cada entrada en un directorio contiene lo siguiente: e. Número de usuario : va del 0 al 15 permitiendo que varios usuarios puedan compartir un disco. f. Nombre de archivo: consta de 1 a 8 caracteres seguidos de 0 a 3 caracteres de tipo de archivo, denominado nombres de archivo . g. Contador de extensión : si un archivo toma más bloques de los que pueden ser apuntados por una entrada, proporciona entradas adicionales. h. Número de registros : las longitudes de los archivos se redondean hasta los 128 bytes más cercanos, de modo que las aplicaciones deben saber la cantidad de datos que hay en el último registro. i. Mapa de asignación : es un grupo de números (o apuntadores) a bloques de disco que contiene los datos para el archivo. 03.Área de almacenamiento de datos: Contiene los bloques de datos para los archivos. Para que el sistema tenga acceso a un archivo, el programa de aplicación del usuario debe proporcionar el nombre del archivo y el sistema de archivos lo busca en el directorio de disco para determinar si un archivo con ese nombre fue guardado en el disco. Los sectores están agrupados entre si en bloques de asignación , que son sectores consecutivos agrupados entre si. El tamaño del disco determina el tamaño de estos bloques de asignación. El BIOS contiene una tabla integrada que proporciona el tamaño de cada una de estas áreas. Además, en el directorio no hay fechas ni horas. Sólo hay un directorio sin subdirectorio. Un archivo debe almacenarse totalmente en un disco. Si el directorio está lleno, también lo está el disco. No hay ningún tamaño de entrada determinado de modo que el tamaño del archivo debe calcularse a partir del número de apuntadores en esta entrada del directorio y medidas posibles. Si el directorio está lleno, también lo está el disco. El tamaño del directorio es fijo, por lo que en un disquete sólo pueden almacenarse 64 archivos o menos. Procesos y multitarea básica La idea era hacer un trabajo en un proceso de fondo mientras se hacía un trabajo en un proceso de primer plano. La solución del CP/M fue un proceso de impresión de fondo. En lo más alto de la memoria debajo del SO se carga un pequeño programa. Este programa se iniciaba a sí mismo y luego le devolvía el control al CCP, permitiendo la ejecución de otro programa. Esto aparentaba que la computadora hacia dos cosas a la vez, es decir multitarea. SO Multitarea Monousuario: Planificación de Procesos: Concepto de Apropiación: es la facultad del SO de quitarle un recurso a un proceso, por ejemplo la CPU. Al agregar apropiación las planificaciones para la CPU que eran para monotarea se pueden modificar para que se conviertan en multitarea: ● FCFS se convierte en Round Robin. En este caso, la apropiación está basada en un quantum de tiempo, dejamos que cada proceso se ejecute una cantidad específica de tiempo sin hacer ninguna operación de E/S. Si el proceso excede ese tiempo, apropiamos la CPU y colocamos ese proceso al final de la cola de ejecución. ● SRTF (R=Runtime) se convierte en SRTF (R=Remaining). ● Prioridad se convierte en Prioridad apropiativa. Acá podemos aplicar apropiación cuando un proceso de prioridad superior entra en el estado listo. Colas multinivel Como indica su nombre, en lugar de una cola única se tienen varias. Todas las colas individuales pueden utilizar el mismo algoritmo de planificación, o pueden utilizar algoritmos distintos. Las colas tienen prioridades diferentes, y la cola con mas prioridad es la que se atiende primero. La mayor parte de los SO modernos cuentan con un sistema de retroalimentación a las colas multinivel. El inicial es que un nuevo proceso es interactivo, de modo que se coloca en una cola de alta prioridad. Si el proceso se ejecuta por más tiempo del permitido por el quantum para esta cola sin hacer ninguna llamada de bloque al SO, entonces el SO supone que en realidad no es un proceso interactivo, de modo que lo mueve hacia la siguiente cola de menor prioridad. Esta cola también puede tener un quantum de tiempo más largo. Entonces, si el proceso no termina en su quantum de tiempo en la cola rápida, quizás sea conveniente darle más tiempo a la cola inferior. Por lo general hay al menos tres de estas colas. La mayoría de estos algoritmos lo que hacen es quitarle prioridad a los procesos que agotan el quantum y dale prioridad a los que tienen más interacción con el usuario. Se muestra un ejemplo a continuación: Dos colas Round Robin y una FCFS. Arriba los procesos de mayor prioridad. Al agotar el quantum cae la prioridad. Evaluación de los algoritmos: Existen varios criterios para evaluar los algoritmos: ● Producción: número de trabajos que se ejecutan por hora o por minuto.. ● Tiempo medio de retorno: tiempo transcurrido desde el inicio hasta el final del trabajo. ● Tiempo de respuesta: tiempo transcurrido desde que se presenta el trabajo hasta el inicio del resultado. ● Utilización de la CPU: porcentaje del tiempo en que la CPU ejecuta trabajos reales (sin intercambiar entre procesos o hacer alguna otra tarea, es de interés primordial en la mayoría de los sistemas). ● Tiempo medio de espera: tiempo que el proceso para en la cola de listo. Otras Consideraciones: Hay otros aspectos que impactan en la planificación de los procesos: ● Planificación a largo plazo: en un SO PC con una GUI, normalmente no existe este planificador. La tarea del programador a largo plazo es decidir cuántos trabajos tratar de ejecutar al mismo tiempo y cuáles trabajos ejecutar cuando. ● Afinidad con el procesador: es importante saber si un proceso es afín a un core de un procesador o no. (Hay computadoras con distintos colores o procesadores, es decir que son mejores para ciertos procesos). ● Modelo de creación de procesos: como se crean los procesos. Hilos: Elmasri Pag 93 PDF Gestión avanzada de memoria: Múltiples procesos con un número fijo de procesos: Los diseñadores de SO comenzaron a buscar mejores formas para organizar el procesamiento. Terminaron por darse cuenta de que el registro de reubicación podía ejecutar un programa en cualquier parte, y no solo en la parte superior del SO residente. Se desplazaron a una organización de la memoria del SO como en la imagen (SO multiproceso con un número fijo de procesos): Ahora que el SO ejecuta múltiples programas y un programa realiza una operación E/S hacia algún dispositivo lento, el SO simplemente coloca la dirección de la memoria del segundo programa en el registro de reubicación y empieza a ejecutar el segundo programa. La solución para evitar que las aplicaciones no pudieran dañarse entre si era agregar un registro límite que pudiera establecer una cota superior más allá de la cual un programa no puede direccionar, justo como no podía direccionar más abajo del establecimiento del registro de reubicación. Cuando el SO cambia de la ejecución de un programa a la de otro, ahora debe fijar tanto el registro de reubicación como el registro límite. Fragmentación interna: Cuando se instala este tipo de SO, el administrador debe decidir cuánta memoria apartar para cada área del programa: una partición. El SO no modifica el tamaño de estas particiones a medida que el sistema está en operación. Ahora el SO está tratando de colocar más programas en la misma partición. El problema con esto es que si hace una partición y se ejecuta un programa de menor tamaño en ella, se estaría desperdiciando el resto de la partición. Este espacio sin usar se denomina fragmentación interna. Podríamos establecer una o dos particiones pequeñas para ejecutar pequeños trabajos rápidos y una o dos particiones más grandes para las aplicaciones grandes. Esto haría tender a minimizar el espacio desperdiciado debido a la fragmentación interna. Múltiples procesos con un número variable de procesos Una solución parcial a la fragmentación interna consiste en no hacer las particiones de tamaño fijo o en un número; en lugar de ello, usamos tanta memoria como se necesite para ejecutar el programa. Cuando ejecutamos el programa le asignamos una cierta cantidad de memoria asignada por el programador. Si este intenta usar más memoria que la indicada por el programador, entonces el SO termina con un error. Cuando un programa termina, el SO vuelve a poner a disposición esa memoria para ejecutar otro programa. Este espacio suele denominarse hueco o fragmento externo. El SO suele mantener una lista de los huecos disponibles Supongamos que tenemos dos huecos, cada uno de 5 MB y que tenemos un proceso por ejecutar que indica que requiere 8MB. Tenemos 10 MB de bloques de memoria libre en los dos huecos (Suficiente para ejecutar este proceso). Pero la memoria libre no está en una pieza, de modo que no podemos ejecutar el programa. Esta situación se denomina fragmentación externa. Debido a que nuestros procesos son reubicables, es posible mover un programa en la memoria aun después que ha comenzado su ejecución. Normalmente el proceso se suspende, se mueve a otra ubicación y vuelve a empezar. El SO sólo tiene que modificar el valor colocado en el registro de reubicación de modo que indique el inicio de la nueva ubicación de la aplicación en la memoria física. Este proceso se denomina compactación . Carga dinámica: El programador decide explícitamente cuando cargar las superposiciones y cuando llamar a las rutinas que están en la superposición. Cuando el SO carga un programa en la memoria principal, podría cargar sólo el cuerpo principal del programa en la memoria. Para acceder a varias subrutinas, podría usar una tabla que muestre cuáles rutinas ya están cargadas en la memoria y cuáles no. Si no cargamos las subrutinas cuando el programa empieza por primera vez, quizá jamás se necesite cargarlas. Si más tarde el programa llama a la rutina, entonces podemos cargarla en ese instante. Bibliotecas de enlace dinámico En este caso la rutina de biblioteca en si no se vuelve parte del programa ejecutable. Dejamos intacta la referencia simbólica a la rutina de biblioteca que produjo el compilador. Así como con la carga dinámica, si nunca se hace referencia a la rutina, entonces no sólo no nos preocupamos por cargarla en la memoria; ni siquiera vinculamos el símbolo con una dirección lógica. Dejamos las rutinas en bibliotecas especiales que suelen denominarse bibliotecas de enlace dinámico o DLL. Observemos que con este mecanismo se obtienen otros varios beneficios al mismo tiempo: ● Puesto que las subrutinas no son parte del programa ejecutable, el programa es más pequeño, de modo que se requiere menos espacio en la unidad de disco y se cargan más rápido en la RAM. ● Normalmente se tienen muchos programas que usan los mismos módulos de la biblioteca. Contar con una sola copia de este código puede ahorrar mucho espacio en el disco. ● Si en uno de los módulos de la biblioteca se ha corregido un error fijo, sólo se necesita corregir esa biblioteca encaminando y cargándola en el sistema, lo que corrige automáticamente ese error en todo programa que haga mención de esa DLL. Hay un problema con las bibliotecas dinámicas. Cuando el desarrollador de un paquete de software está usando un conjunto particular de funciones en una biblioteca de enlace dinámico, su código podría depender también de errores corregidos en una versión particular de la biblioteca. Este problema se denomina coloquialmente infierno de las DLL. Paginación En lugar de usar el registro base para verificar una dirección, lo utilizamos para reubicarse. Esto nos permitió la reubicación dinámica. Sin embargo, encontramos que el hecho de permitir que programas de tamaño variable entren y salgan de la memoria provocaba fragmentación externa. Desafortunadamente, la compactación es solo una tarea que hace el SO para que las cosas funcionen mejor en sentido global. Finalmente se desarrolló otra solución: dividimos el espacio de la memoria en bloques de tamaño fijo, y en lugar de asignar a una aplicación todo el espacio que necesita en un gran segmento, le asignamos una cantidad suficiente de bloques más pequeños para proporcionarle lo que necesita. Los bloques que asignamos pueden estar en cualquier parte de la memoria porque solicitamos a la MMU que reasigne dinámicamente cada bloque por separado. Esta técnica se denomina paginación. Dividimos el espacio en direcciones físicas en bloques de tamaño uniforme, que denominamos marcos potencia . El número de bytes en un bloque siempre es una de 2. La CPU genera una dirección de la memoria. En general, el programa ignora el hecho de que la memoria se manipula en páginas separadas. La MMU considera que la dirección está compuesta por dos partes, mostradas aquí como el número de página, p , y el dirección del byte desplazamiento , d . El desplazamiento es la específico dentro del marco. El resto de la dirección lógica es el número de página. Tendremos un registro que guarda la dirección de la memoria de la tabla de páginas para el proceso en ejecución. Se denomina registro de dirección de la tabla de páginas. La unidad de control de la memoria añade el número de la página de la dirección lógica que genera el proceso en ejecución en la CPU al valor en el registro de dirección de la tabla de páginas. El valor almacenado en esa ubicación de la tabla de páginas es la dirección de reubicación del marco particular al que se está intentando tener acceso. Accesos requeridos a la memoria dual Aunque ya hemos descrito este mecanismo. Para cada referencia a la memoria es necesario hacer una segunda referencia, a fin de encontrar en la tabla de páginas la entrada a utilizar como factor de reubicación para esta página. Nuestra solución es que la unidad de gestión de la memoria guarde en memoria caché los factores más recientes de reubicación, de modo que podamos usarlos nuevamente sin necesidad de buscarlos en la memoria. Esto se lleva a cabo con un dispositivo especial de hardware denominado búfer duplicado de traducción , o TBL (translation lookside buffer). La esencia de estos circuitos es que cuando intentan verificar si ahí hay un número de página, todas las entradas se buscan en paralelo. Las entradas en el TBL no tienen que mantenerse en ningún orden. Control de acceso a la memoria Cuando teníamos accesos a la memoria principal con un registro de reubicación para todo el programa también teníamos un registro que prohibía que un proceso accediera fuera del área de la memoria que tenía asegurada. Con hardware de paginación se requiere un mecanismo semejante. Se requieren algunos mecanismos para limitar el acceso a la tabla de páginas. Para este problema hay dos enfoques. El primer enfoque consiste en usar un tamaño fijo de tabla de páginas. En este caso se requiere un bit válido en cada palabra de la tabla de páginas para indicar si una dirección de la tabla de páginas es correcta. El otro enfoque de control de acceso a la memoria consiste en usar una tabla de páginas de tamaño variable. En este caso, se tiene un registro de longitud de la tabla de páginas. Con un solo rastreo de reubicación se tenía un registro que especificaba la longitud del proceso en la memoria principal. Es decir, contiene la dirección del número de página más grande para un proceso. Si una dirección generada por la CPU contiene un número de página más grande que el número en el registro de longitud de la tabla de páginas, el hardware genera un error de interrupción de direccionamiento. Protección de acceso a páginas La paginación, permite que el SO restrinja los tipos de acceso posibles a las diversas páginas. El hardware puede fijarse para sólo permitir acceso de lectura a una página, o para ejecución. Tablas de páginas grandes En máquinas modernas con SO, los programas se están volviendo muy grandes. Esto significa que las tablas de páginas también son muy grandes. Se ha vuelto cada vez más difícil gestionar la memoria asignada a las tablas de páginas en sí. Para tratar con estas grandes y dispersas tablas de páginas se han adoptado varios enfoques. La primera técnica consistió en hacer una tabla de páginas multinivel. En una tabla de páginas de dos niveles (Imagen insertada abajo): esencialmente se página la tabla de páginas. La MMU considera la dirección lógica generada por la CPU como si estuviese compuesta por varias partes; en este caso, tres. Tenemos el desplazamiento de páginas, que será llevado y usado como el marco de desplazamiento. Consideramos los números de página como p1 y p2; p1 será utilizado por el hardware para tener acceso al nivel superior de la tabla de páginas. Los bits restantes del número de página, mostrados como p2, se usan para tener acceso a la tabla de páginas de segundo nivel seleccionada. Esta entrada es el número de marco para el número de página representado en la dirección original por p1 y p2 juntas. Este número de marco se usará con el desplazamiento original para tener acceso a la ubicación de la memoria deseada en la memoria física. Tabla de páginas invertida Un enfoque ligeramente diferente al problema de la memoria externa consistió en invertir el problema. La idea era asignar lo marcos físicos en páginas lógicas. La tabla se mantiene en orden a través del número de marco físico. Se busca en la tabla en sí para encontrar una referencia. Puesto que sólo hay una tabla, los números de página de los diversos procesos no son suficientes para especificar el mapeo. El tiempo para buscar una tabla de páginas invertida a menudo es más lento que para una tabla de páginas normal. El SO puede acelerar esta búsqueda al usar una función hash o de distribución para tener acceso a la tabla. Dependemos bastante de la búsqueda en TLB. Las tablas de páginas invertidas requieren mucho menos RAM que las tablas de páginas normales. Tablas de páginas con múltiples tamaños de página En sistemas posteriores se volvió común tener más de un tamaño de tabla de páginas. La razón de esto es que el núcleo del SO puede mapearse en la tabla de páginas. La mayor parte de las páginas del núcleo serán las mismas en todo proceso; nunca mueven de su lugar, causan fragmentación y siempre están ahí, de modo que no es necesario dividirlas en páginas pequeñas. Algunas veces las páginas ni siquiera están en la memoria. Este no suele ser el caso con el núcleo. En consecuencia, tener una sola página para mapear el núcleo es una gran ventaja puesto que puede fijarse y manipularse más fácilmente y sólo se requiere una entrada del TLB para mapearlo. Segmentación La segmentación sería una pista de desarrollo diseñada principalmente para ayudar a resolver los mismos problemas que solucionaba la paginación, además de algunos otros. Esta técnica se denomina segmentación. La segmentación surgió de la observación de que un programa puede considerarse como si estuviese compuesto por varias partes. Se tiene una rutina principal y a menudo se cuenta con subrutinas y funciones que son reconocidas por el compilador como elementos por separado. Algunas veces se compilan por separado y se colocan en bibliotecas. Cada una de estas partes puede considerarse independiente de las otras y puede tener un espacio de direcciones lógicas por separado. Consideramos que el espacio de dirección está separando en: número de segmento (s) y un desplazamiento (d). Con la segmentación tenemos un número más o menos pequeño de segmentos, cada uno de los cuales puede ser razonablemente grande en sí, de modo que el número de segmentos en general es un número más pequeño de bits y el desplazamiento dentro del segmento es de tamaño más grande. Normalmente el programador no ejerce ningún control manifiesto sobre la segmentación. Los compiladores generan segmentos por separado para las porciones más importantes del módulo que se está compilando, y colocan referencias simbólicas en los módulos de objeto. El ligador asigna número de segmentos reales para ser usados cuando se combinan los módulos objeto en el programa binario ejecutable y para que el SO los use cuando se cargue dinámicamente módulos de bibliotecas. La subrutina usará la entrada de la tabla de segmentos especificada por el número en la parte del segmento de la dirección. Tomará el apuntador que se encuentra en esa entrada de la tabla de segmentos y lo añadirá a la parte de desplazamiento de la dirección lógica. Hardware de paginación sustituyó el número de página con un número de marco. Puesto que los segmentos son de variable, también pueden ubicarse en cualquier parte, de modo que para obtener la dirección de la memoria física usamos el apuntador de la tabla de segmentos más el desplazamiento.. Así, los sistemas con segmentación también usan TLB para acelerar el acceso. Esta no es una solución óptima para evitar fragmentación externa. Sigue siendo necesario seguir la pista de los huecos de la memoria. En consecuencia, se tendrá algo de fragmentación interna. Pero ahora la variación del tamaño de los huecos es menor que la variación que se tenía que considerar al seguir la pista de procesos enteros. En consecuencia, tendremos menos problemas con fragmentación externa. Puesto que los segmentos son de tamaño variable, es necesario contar con un mecanismo para que el sistema verifique las direcciones de modo que sea posible tener la certeza de que el proceso no se está direccionando fuera de los límites del segmento. Es posible incrementar la protección que se está proporcionando al sistema al limitar los tipos de accesos que se hacen a los diversos segmentos. Cada segmento es común tener un conjunto de banderas grandes que controlan los tipos de accesos que pueden hacerse. En algunos SO es posible que los procesos compartan segmentos. La gestión de los número de segmentos a través de múltiples procesos puede ser bastante engorroso para el SO. Los programadores de lenguajes de alto nivel en general no está enterados de que un SO está usando segmentación. Los programadores en lenguaje de nivel bajo deben estar enterados de la segmentación y la forma en que el SO la usa y pueden controlar la segmentación en caso necesario. Segmentación con paginación Hay una diferencia fundamental entre paginación y segmentación. La paginación es transparente para el proceso en ejecución. Un programa de aplicación que fue creado para su ejecución en un SO donde el proceso asignado es una gran partición única puede ejecutarse sin modificación en un sistema que use una arquitectura de memoria paginada. La segmentación, por otra parte, requiere que de alguna manera los programas están estructurados de modo que puedan dividirse en partes lógicas con diferentes espacios de dirección. Con un diseño de hardware idóneo es posible ejecutar una arquitectura de programa segmentado en combinación con una arquitectura de memoria paginada. Hay dos formas en que es posible combinar segmentación y paginación. En el primer diseño se tiene una tabla de páginas para cada segmento, en lugar de una sola tabla de páginas para el proceso. El segundo diseño sigue habiendo una tabla de segmentos pero, en lugar de apuntar a tablas de páginas separadas para cada segmento, las direcciones en la tabla de segmentos están dentro de un espacio de dirección lineal, que luego se mapea a la memoria física de la misma manera en que funciona un sistema paginado. La mayor parte de los SO modernos usan este último mecanismo de una u otra forma aunque limitan el uso de los segmentos. Los segmentos se usan para restringir el direccionamiento y controlar el acceso. Paginación por Demanda: A medida que los programas se ejecutan no requieren tener acceso aleatoria mente a las direcciones en todo su espacio de direcciones lógicas. A las instrucciones en el segmento de código se accede secuencialmente, de modo que para alrededor de mil instrucciones podría accederse a una sola página en la porción del código del espacio de direcciones lógicas. O bien, el programa podría entrar en un bucle, algunas veces durante un largo lapso y permanecer en una sola página de código. Cuando dividimos la ejecución de un programa en pequeñas porciones de tiempo, normalmente encontramos que el proceso sólo accede a unas cuantas páginas en cualquier porción de tiempo dada. Este fenómeno es muy importante en el diseño del SO. Denominado localidad de referencia. El truco para aprovechar este fenómeno se denomina paginación por demanda . Se modifica ligeramente el significado del bit válido en la tabla de páginas. Ahora el bit indica que no hay marco asignado a esta página. Cuando cargamos la primera página fijamos su bit válido en verdadero para indicar que está en la memoria. Marcamos el bit válido de cualquier otra página para mostrar que está página no está en memoria. Luego se inicia la ejecución de un programa. El SO puede conectarse con el proceso en la memoria y dejar que el mecanismo de fallo de página traiga incluso la primera página del programa. Esto se denomina carga perezosa. Si la referencia es una página que no está en el espacio de direcciones lógicas del proceso, el programa ha cometido un error y se origina una excepción de direccionamiento, con lo cual es muy probable que aborte el proceso. Si la dirección que ha provocado un fallo está en el espacio de direcciones lógicas del proceso, simplemente la página no se ha asignado en la memoria física, ya sea porque nunca ha sido llevada a ésta o porque ha sido sacada de ahí. Esta condición se denomina fallo de página . EAT con Paginación por Demanda: Consideremos lo que ocurre cuando tenemos acceso a una página que no está en la memoria. Nuestro tiempo de acceso efectivo consta de cuatro componentes. La tabla E/S del disco rebasa ampliamente las velocidades de la memoria. Esta dominación conduce a varios mecanismos que parecen complicados que se han desarrollado simplemente para evitar efectuar una operación de E/S en un sólo disco para paginación por demanda. El conjunto de trabajo y reemplazo de página: A medida que se ejecuta un programa, este hace referencia a algún conjunto de páginas, este grupo al que hace referencia un proceso en un breve lapso se denomina conjunto de trabajo . Este conjunto se lo mide sobre un intervalo fijo denominado ventana deslizante proceso tiene . Resulta normal encontrar que un varias páginas en la memoria a las que ya no hace referencia. Lo que sería lógico es identificar esas páginas y eliminarlas de la memoria una vez que ya no sean necesarias. Desafortunadamente, el no haber referenciado alguna página durante un tiempo no significa que la siguiente instrucción no lo haga. Por suerte, eliminar una página que será necesaria más tarde no causa ningún problema, sólo que no es eficiente, la siguiente referencia a la página originaria un fallo de página , de modo que la buscaría de nuevo. Existe una estrategia de reemplazo muy simple: 1. FIFO ( primera en entrar, primera en salir ): El SO mantiene una cola con los números de páginas de acuerdo a cómo estas van entrando para cada proceso y simplemente se expulsa la más antigua. El algoritmo es de baja sobrecarga (poca carga de parte del SO), es barato y fácil de comprender e implementar. 2. Algoritmo de reemplazo de página óptimo: Cuando es necesario reemplazar una página, el SO sustituye la página cuyo uso siguiente será el más alejado en el futuro. Imposible de implementar ya que necesita saberse si una página será usada en un futuro. 3. Página menos usada recientemente: Se establece la hipótesis de cual pagina es la que tiene mayor probabilidad de no ser usada nuevamente, de modo que se la quita. 4. Algoritmo del reloj: Es el más sencillo, el hardware puede asegurar cuando se hace referencia a una página, en una entrada de la tabla de páginas se establece un bit, denominado bit de referencia a la página de acceso o bit o bit de uso , el hardware verifica ese bit. Si ya está establecido, no se hace nada. Caso contrario es encendido. El SO puede limpiar estos bits para las páginas que están actualmente en memoria. El hardware enciende a los bits para todas las páginas a las que se está haciendo referencia. Cuando se requiere hacer una página se busca en la tabla y si se encuentra una página con un bit válido encendido y un bit de referencia que se limpia, podrá ser reemplazado. Paginas sucias: Cuando una parte de un programa se carga en una página y se sustituye por otra cosa, no es necesario guardarlo, porque es posible volver al programa original y obtener la página se de nuevo se hace referencia a ella. Sin embargo, si una página contiene datos y se ha modificado parte del contenido, entonces no es posible reemplazarla. Las páginas que han sido modificadas se denominan páginas sucias se , las cuales escriben en un sitio especial del almacenamiento secundario, denominado archivo de intercambio (swap) o almacenamiento de respaldo (backing store). En consecuencia, este archivo de intercambio actúa como una extensión de la memoria primaria del sistema, dando origen a la expresión memoria virtual . Más algoritmos de reemplazo de páginas: 1- Algoritmo de segunda oportunidad: Modificación del algoritmo de reloj, busca a través de la tabla de páginas, si el bit de referencia está establecido, entonces lo limpia. Actualiza los bits de referencia. A medida que se desplaza a través de la tabla, si no encuentra ninguna que esté libre en la primera revisión, encuentra algo en la segunda. Las operación de fondo no son tareas que se efectúan cuando en el estado de listo hay procesos de alta prioridad. Así, las instrucciones que se ejecutan en una tarea de fondo no lo hacen a costa del proceso de cualquier usuario, de modo que son más o menos libres. 4. Algoritmo no utilizado recientemente (NRU) o Algoritmo no utilizado (NUR): Las páginas se dividen en cuatro clases según las posiciones de estos dos bits: 4.3Limpio y sin referencia 4.4Sucio pero sin referencia 4.5Limpio pero con referencia 4.6Sucio con referencia En la primera clase se busca encontrar páginas sin referencia y limpia para poder usarse de inmediato. Si no se encuentra, vuelve a buscarse de nuevo en la clase dos y así sucesivamente. Cuantas paginas por cada proceso? Podemos estudiar programas en ejecución en un sistema prototipo y fijar algún límite arbitrario. Pero si no se cuenta con los suficiente procesos en ejecución para llenar con páginas toda la memoria, se producen fallos de páginas cuando no se las desea. Por lo que no es buena idea. Es posible hacer que el sistema sea un poco más dinámico. 1- Asignación equitativa: Dividir el número de páginas disponibles entre el número de procesos en ejecución. 2- Asignación proporcional: Deducir que programas puedan utilizar más páginas comparar sus tamaños. Balance automático del límite de páginas: La mayor parte de los SO usan este mecanismo. Alguno de estos son variantes del algoritmo de la frecuencia de fallo de página y depende de la ide de que la tasa de fallo de un proceso es un buen indicador de si se tiene el número correcto de páginas. Si hay muy pocas páginas, la tasa de fallo de página aumenta rápidamente. Si no se está generando ningún fallo, también puede tener páginas en la RAM que no se utilicen. Este mecanismo establece un límite superior y un límite inferior para la tasa de fallo. Este mecanismo tiende a mantener a todos los procesos del sistema que están ejecutándose a una tasa de fallos de página semejantes y sólo asigna tantos marcos a un proceso como sea necesario para permanecer en ese intervalo. Hiperpaginación: La hiperpaginación es un fallo generado por la sustitución de páginas en un proceso ya asignado dando como consecuencia poco trabajo real y reflejando en el sistema una excesiva cantidad de E/S en el disco. Si la suma de los conjuntos de trabajo de todos los procesos en ejecución es mayor que la memoria principal real, todo el sistema dedica más tiempo reemplazando páginas que el que dedica para la ejecución de procesos y entonces se dice que el sistema está efectuando hiperpaginación. Bloqueo de Página: Un SO que está haciendo paginación por demanda debe permitir que una aplicación asegure una página de modo que el mecanismo de paginación no la seleccione. Mecanismos de página limpia: Para el reemplazo resulta importante usar una página limpia, en lugar de una sucia, para que ésta no tenga que ser escrita en el archivo de intercambio. Podemos reducir el impacto de usar una página sucia al mantener disponible para su uso un grupo de marcos libres que estén limpios. Cuando el algoritmo de reemplazo de página selecciona una página sucia para esta acción, el SO puede usar uno de los marcos limpios del grupo de marcos disponibles. Luego, en el fondo, el contenido de la página sucia suele escribirse fuera del disco. Cuando la página está limpia, el marco puede colocarse en el grupo de marcos disponibles. Otra tarea que es posible efectuar en el fondo es limpiar páginas que estén sucias. Temas Especiales de Gestión de la Memoria Distribución de la Memoria entre Procesos: Tanto la paginación como la segmentación permiten que porciones de la memoria sean compartidas entre procesos. Con esto se pueden lograr grandes ahorros de la memoria. El mecanismo copiar al escribir dirección consiste en compartir todo el espacio de física entre dos procesos, pero a medida que se ejecutan, los cambios hechos por un proceso no son vistos por el otro. Archivos Mapeados en Memoria: La mayor parte de los SO modernos permiten un modo especial de distribución de la memoria denominado archivos mapeados en memoria proceso . En este modo un solicita al SO abrir un archivo y asociar todos los datos o parte de ellos en el archivo con una región del espacio de direcciones lógicas del proceso. Luego, el proceso puede referir la información en ese espacio como un arreglo o a través de apuntadores de memoria. Este sistema cuenta con dos ventajas principales. La primera es que el proceso no tiene que usar declaraciones de E/S para tener acceso a los datos; el sistema de paginación por demanda se hace cargo de tener acceso a los datos idóneos desde el archivo. La segunda ventaja es que dos o más procesos pueden pedir al SO acceso al mismo archivo al mismo tiempo. Los mismos marcos de la memoria se asignan a los espacios de direcciones lógicas de ambos procesos, permitiéndoles compartir el acceso a la memoria. Mac OS: Gestión de Archivos: System 1: Los programas se guardaban en disquete y cargados en la RAM cuando iban a ejecutarse. Aunque los archivos se guardaban en un directorio único, existían carpetas virtuales, donde cada archivo podría marcarse con el nombre de una carpeta. System 3: Se implementó un Sistema de Archivos Jerárquico (HFS) reemplazando el MFS, permitió aumentar cualquier número de sectores que fueran potencia de dos. Permitiendo mayor almacenamiento, pero se podía desperdiciar mucha memoria. Entradas: guardaba metadatos como cuando se creó, quien, etc. Los nombres de archivos eran hasta 32 caracteres. System 8: Utilizaba una versión del Sistema de Archivos Jerárquico Plus (HFS+), usaba un apuntador de 32 bits y era capaz de direccionar directamente a una unidad de disco de 4GB, utilizando un bloque de asignación de 32 sectores. Gestión de Procesamiento: System 1: ➔ Tareas únicas: al tener que ser asequible económicamente para los usuarios, estas deberían correr con una memoria muy limitada, por esto se tuvo que renunciar a la multitarea. Aunque las ventanas no ocupaban toda la pantalla, no se podía ejecutar más de una aplicación a la vez, no para impresión a fondo. System 2: ➔ Multitarea Virtual: ◆ Swicher creó varias ranuras fijas en la RAM (donde se cargaban las aplicaciones). Asigna un montículo separado para cada para aplicacion que inicie. ◆ Switcher realiza una interrupción de contexto para que los SO pueda empezar a trabajar con la nueva aplicación (multitarea muy limitada). System 4: ➔ Multifinder: ◆ Permite ejecutar más de una aplicación a la vez, el usuario puede elegir entre Multifinder y Finder. ◆ A diferencia del Switcher, este permite que cada programa continuará su ejecución, dando a cada uno tiempo de la CPU. ◆ Multitarea Cooperativa: un proceso se podía ejecutar todo el tiempo que quisiera hasta que haga una petición al SO. Si necesitaba un recurso pasaba a la lista de [Bloqueados], estos hacen a menudo una llamada especial para ceder la CPU (pero aun no termino su proceso), pasando a [Listos]. System 7: ➔ CPU: ◆ Debido a que empezaron a utilizar PowerPC, requirió cambios en el diseño del SO, pasó de utilizar una arquitectura CISC a RISC, lo que requería menos electrónica, el conjunto de instrucciones son sencillas pero se requieren mayor cantidad de instrucciones. ◆ Una parte del código emulaba un nanonucleo gestionado por la CPU, este se ejecutaba en modo supervisor, proporcionando una interfaz de bajo nivel para gestionar el hardware. Este iniciaba un emulador 68000 cuando iniciaba el sistema, emulando sólo una instrucción de usuario del 68000 sin emular la MMU, permitiendo mayor compatibilidad. ◆ Los programas se podian compilar en módulos ejecutables tanto en código nativo 68000 como en código PowerPC, a estos se los denominaba Binarios Gruesos. El intercambio entre ambos módulos se llevaba a cabo mediante un conjunto de rutinas de bibliotecas denominado Gestor de fragmentación de código. System 8: ➔ Procesador: ◆ Una aplicación podia usar mas de una CPU, debido a que se introdujo la idea de permitir que una aplicación se dividiera en múltiples hilos independientes (tareas en Mac OS). Para esto se modificó el nanonucleo para hacer posible el multihilo. ◆ Ahora existen prioridades asociadas a tareas, esto permite que el SO pudiera diseñar tareas como más importantes que otras. ◆ Contaban con multiples CPU, por lo tanto realmente dos programas corrían al mismo tiempo. El SO lo soportaba gracias al sistema de Multiprocesamiento simétrico, en la cual el SO se ejecutaba en cualquier CPU disponible. Gestion de Memoria: System 1: ➔ Memoria: ◆ Tenía una arquitectura plana (espacio de direccionamiento único), donde en cualquier instante, cualquier instrucción puede hacer referencia directamente a la memoria. ◆ La CPU 68000 tenia direcciones de 24 bits, no había protección de la memoria, por lo cual cualquier programa puede modificar cualquier cosa de ella, incluyendo el SO (modo supervisor ). ◆ A5word tenía un tamaño fijo y contenía los datos estáticos de la aplicación y algún metadato de ella. El SO carga el registro A5 de la CPU con un apuntador hacia ella de modo que la aplicación se abría dónde están sus datos. ◆ Para el tamaño del montículo, establece un límite superior cuando empieza la aplicación, este es controlado por la rutina de asignación de memoria para controlar el límite. Pero la pila es controlada por el hardware y debido a que la subrutina y funciones se llaman y regresan, a la pila se la introduce y extrae datos (no hay protección de hardware contra la expansión del mismo). Una vez que la aplicación terminaba, se borra su monticulo. ◆ Un subsistema Stack Sniffer se ejecutaba durante el intervalo de trazado vertical del monitor (60 veces por segundo), comprobando el nivel de la pila contra el límite. ◆ Para evitar la fragmentación de la memoria administra bloques de memoria reasignables, accediendo a estos indirectamente por medio de un bloque del apuntador maestro . Eran de 24 bits para el direccionamiento y 8 superiores para banderas (“bloqueado”, “purgable” o “recurso”). Foto ➔ ROM: ◆ Además de contener la BIOS y el código POST, contenia gran parte del SO. Principalmente para evitar llenar el almacenamiento disponible en un disquete, para que el SO cargue más rápido y además que los clones puedan ejecutar Mac OS. System 4: ➔ Memoria: ◆ Con Multifinder las aplicaciones pueden comunicar sus requerimientos de memoria al SO según sus necesidades (a veces no era suficiente para algunas tareas). El usuario podrá cambiar este número. ◆ Si un programa corría bajo el único Finder , debía trabajar sin cambio bajo Multifinder es bastante semejante. , ya que la arquitectura de la memoria System 6: ➔ Memoria: ◆ Maneja el direccionamiento verdadero de 32 bits, debido a la aparición de la CPU 68020 de Motorolla. ◆ Mantiene compatibilidad para ejecutar aplicaciones de 24 bits. System 7: ➔ Memoria Virtual: ◆ Es una técnica que utiliza parte del disco duro como para simular memoria primaria más grande, utilizando cuando se requiere más memoria de la que posee. ◆ Cuando un programa inicia su ejecución, sólo la primera pagina (división de bloques de la memoria) se lleva a la RAM. Cuando hace referencia a una parte que no está en memoria, como el hardware, provoca una interrupción llamada “fallo de página ”, y el SO lee la página faltante del disco y la carga en memoria. ◆ La computadora debe tener una unidad de gestión de memoria especial, para traducir las generadas por el direcciones lógicas programa en ejecución en la CPU y traducirlas en una dirección física. Gestion de E/S: System 1: ➔ GUI: ◆ Tenía una zona de escritorio, ventanas, iconos, ratón, menús y barra de desplazamiento. Este era muy limitado pero se trataba de una GUI, siendo más amigable que la consola. Las ventanas eran dibujadas por el SO, lo que facilitaba la adecuación a un nuevo programa. System 2: ◆ Finder más rapido. escoger Choose Printer , permite al usuario una impresora. ➔ GUI: ◆ Switcher, permite al usuario iniciar varios programas. ◆ Los programas en ejecución “tenían foco” (asi se podia cortar y pegar entre aplicaciones). ◆ Los disquete pueden ser expulsados al arrastrarlo a la papelera. System 3: ➔ Redes: ◆ Chooser gana importancia gracias al soporte de AppleShare : protocolo para compartir archivos, AppleTalk : la capa de redes y LocalTalk: cada de enlace de datos y física. System 4: ◆ Soporte para unidades de disco mayores a 32MB. ➔ GUI: ◆ Coexistencia entre ventanas de distintas aplicaciones, cada aplicación podría tener múltiples ventanas. ◆ Al tener foco, todas sus ventanas pasaban a la primer capa por tema de compatibilidad con ventanas API existentes. System 7: ◆ Desapareció el Finder. La multitarea cooperativa sería el modo normal de trabajar. ➔ GUI: ◆ Mejora en cuanto a la usabilidad y en el área de la GUI. Permite arrastrar texto de una aplicación a otra. ➔ E/S: ◆ Se introdujo PC Exchange , un software que permite acceder a disquetes con formato MS-DOS . Aunque eran físicamente idénticos, no se podían leer ya que el formato de bajo nivel eran distintos. ◆ El principal bus del sistema se denominaba NUBUS , ya que estaba registrado, sólo Apple podría ejercer el control de la firma sobre todo el desarrollo del hardware. ◆ Las ranuras para PC Card permitían la inserción de un dispositivo que no estaba integrado originalmente en una laptop. ◆ Esta versión era demasiado grande para caber un disquete de 1.44MB, por lo que se necesitaba un disco duro. System 8: Agregó soporte para una nueva clases de dispositivos como USB y FireWire.