Conceptos Fundamentales de Sistemas Operativos: Arquitectura, Gestión y Sincronización

Enviado por Chuletator online y clasificado en Informática y Telecomunicaciones

Escrito el en español con un tamaño de 19,86 KB

Tipos de Sistemas Operativos y sus Características

Sistemas de Procesamiento en Serie

En los inicios de la computación, los sistemas operaban con grandes consolas. Los trabajos se ejecutaban de forma secuencial, sin interacción directa del usuario durante su procesamiento. Un trabajo se entregaba, se ejecutaba y, al finalizar, se obtenía un resultado. La gestión era sencilla, a menudo controlada por un único operador o un sistema de control de trabajos (JLC).

Sistemas por Lotes (Batch Systems)

Estos sistemas eran similares a los de procesamiento en serie, pero los trabajos se agrupaban en lotes. Los programadores entregaban sus trabajos al operador, quien los organizaba y ejecutaba en secuencia. Inicialmente, la CPU permanecía ociosa mientras se esperaban las lentas operaciones de entrada/salida (E/S) de dispositivos como tarjetas perforadas. Con la introducción de los discos, estos actuaron como buffers, permitiendo leer datos por adelantado y guardar resultados temporalmente. El concepto de Spooling (Simultaneous Peripheral Operations On-Line) surgió para superponer las operaciones de E/S con el cómputo, mejorando significativamente el rendimiento.

Sistemas por Lotes con Multiprogramación

Una evolución de los sistemas por lotes, donde el Spooling se utilizaba para mantener una reserva de trabajos listos para ejecutar. El Sistema Operativo (SO) podía tener múltiples trabajos en memoria (o en disco, listos para cargar). Cuando un trabajo realizaba una operación de E/S y quedaba bloqueado, el SO podía cambiar a otro trabajo en memoria, manteniendo la CPU ocupada. Existía un área auxiliar (disco) donde los procesos esperaban para ser cargados en memoria principal y participar en la multiprogramación.

Sistemas de Tiempo Compartido (Time-Sharing Systems)

Representan una extensión lógica de la multiprogramación. Su objetivo principal es permitir la comunicación interactiva entre el usuario y el sistema (por ejemplo, entrada por teclado y respuesta por pantalla). Los usuarios interactúan mediante enunciados de control. Estos sistemas lograron un uso eficiente de los recursos y un costo aceptable. La planificación y la multiprogramación son fundamentales para dar la ilusión de que cada usuario tiene el sistema para sí mismo, compartiendo el tiempo de la CPU. Cuando un proceso realiza E/S o su "cuanto" de tiempo expira, la CPU no queda ociosa; se cambia a otro proceso. El sistema mantiene múltiples trabajos en memoria para facilitar esta conmutación rápida.

Sistemas Paralelos (Multiprocesador)

También conocidos como sistemas multiprocesador, consisten en múltiples CPUs fuertemente acopladas que comparten un bus, memoria principal y periféricos. Ofrecen varias ventajas: mayor rendimiento, mayor confiabilidad (si un procesador falla, el sistema puede continuar operando con una degradación gradual) y, a menudo, una mejor relación costo-rendimiento. Al tener más procesadores, los trabajos pueden completarse en menos tiempo. Se distinguen dos tipos principales:

  • Multiprocesamiento Simétrico (SMP): Cada procesador ejecuta una copia idéntica del Sistema Operativo y se comunican entre sí.
  • Multiprocesamiento Asimétrico (AMP): Un procesador (maestro) controla el sistema y las operaciones de E/S, mientras que los otros procesadores (esclavos) realizan tareas específicas asignadas por el maestro.

Sistemas Distribuidos

A diferencia de los sistemas paralelos, los sistemas distribuidos no comparten memoria principal. Se basan en la comunicación entre procesadores que pueden ser idénticos o diferentes, y que están interconectados a través de una red. La computación se distribuye entre estos procesadores. Las razones clave para su uso incluyen:

  • Compartición de Recursos: Permiten compartir recursos (hardware, software, datos) entre diferentes nodos.
  • Computación más Rápida: Al distribuir la carga de trabajo, pueden lograr una mayor velocidad de procesamiento.
  • Confiabilidad: La falla de un nodo no necesariamente detiene todo el sistema, ya que otros nodos pueden asumir sus funciones.

Protección de Hardware y Modos de Operación

Protección por Hardware

Inicialmente, en sistemas monousuario, el usuario tenía control total sobre el hardware. Sin embargo, con la evolución de los sistemas operativos, el SO asumió el control. Surgieron problemas tanto en entornos monousuario como multiusuario, especialmente relacionados con errores de diseño del SO o fallos de hardware. Cuando el hardware detecta un error, el SO debe manejarlo, lo que a menudo resulta en un fin anormal del programa (por ejemplo, un volcado de memoria a un archivo para depuración).

Operación en Modo Dual

Para proteger el Sistema Operativo, los programas de usuario y los datos, el hardware proporciona diferentes modos de operación, generalmente indicados por un "bit de modo". Como mínimo, existen dos modos:

  • Modo Kernel (o Modo Supervisor/Modo Privilegiado): Es el modo en el que se ejecuta el Sistema Operativo. Las instrucciones privilegiadas (como las de E/S) solo pueden ejecutarse en este modo. El sistema arranca en modo kernel.
  • Modo Usuario: Es el modo en el que se ejecutan los programas de usuario. Las instrucciones privilegiadas no pueden ejecutarse en este modo. Un intento de hacerlo genera una interrupción.

Las interrupciones y las llamadas al sistema hacen que el control pase del modo usuario al modo kernel. Es crucial que un programa de usuario no pueda borrar o modificar el Sistema Operativo, lo que se evita mediante esta distinción de modos.

Protección de E/S

Para evitar que un programa de usuario realice operaciones de E/S no válidas o peligrosas, las instrucciones de E/S son privilegiadas. Esto significa que solo pueden ejecutarse en modo kernel. Si un programa de usuario necesita realizar una operación de E/S, debe hacerlo a través de una llamada al sistema, que es una solicitud al SO para que realice la operación en su nombre.

Protección de Memoria

La protección de memoria es esencial para evitar que un proceso acceda a la memoria de otro proceso o a la memoria del Sistema Operativo. Esto se logra, por ejemplo, mediante el uso de dos registros de hardware:

  • Registro Base: Contiene la dirección de memoria física más pequeña permitida para un proceso.
  • Registro Límite: Contiene el tamaño del rango de direcciones lógicas que el proceso puede usar.

Cualquier intento de acceso a memoria fuera del rango definido por estos registros genera una interrupción, protegiendo así las instrucciones y rutinas del SO, así como la memoria de otros procesos.

Protección de CPU

Para evitar que un programa de usuario entre en un bucle indefinido y monopolice la CPU en un sistema de tiempo compartido, se utiliza un temporizador. El temporizador es un dispositivo de hardware que genera una interrupción después de un período de tiempo predefinido. Esta interrupción es una operación privilegiada. Cuando el temporizador interrumpe, el control pasa al SO, que puede entonces decidir si el proceso ha excedido su tiempo asignado y, si es así, cambiar a otro proceso. Esto es fundamental en los sistemas de tiempo compartido para garantizar una distribución equitativa del tiempo de CPU.

Gestión de Procesos y Planificación de CPU

Estados de un Proceso

Un proceso puede encontrarse en diferentes estados a lo largo de su ciclo de vida. Comúnmente, se identifican cinco estados principales:

  1. Nuevo: El proceso está siendo creado.
  2. Listo: El proceso está esperando ser asignado a un procesador. Hay "n" procesos listos.
  3. Ejecución: El proceso está utilizando la CPU. Solo puede haber un proceso en ejecución por CPU.
  4. Bloqueado (o Espera): El proceso está esperando que ocurra algún evento (por ejemplo, una operación de E/S, la finalización de un proceso hijo, la llegada de una interrupción).
  5. Terminado: El proceso ha finalizado su ejecución.

Los procesos en estado "listo" o "bloqueado" se organizan en diferentes colas (por ejemplo, cola de listos, colas de espera por E/S).

Planificadores del Sistema Operativo

Los planificadores son componentes del SO encargados de seleccionar qué proceso debe ejecutarse a continuación. Existen diferentes tipos de planificadores, cada uno con un propósito específico:

  • Planificador a Largo Plazo (Long-Term Scheduler):
    • Controla el grado de multiprogramación (número de procesos en memoria).
    • Selecciona procesos del disco (cola de trabajos) para cargarlos en la memoria principal (cola de listos).
    • Su objetivo es mantener un grado de multiprogramación estable.
  • Planificador a Corto Plazo (Short-Term Scheduler o Despachador):
    • Selecciona uno de los procesos en la cola de listos para asignarlo a la CPU.
    • Se ejecuta con mucha frecuencia (milisegundos).
    • Es el más importante para la actualidad del sistema.
  • Planificador a Medio Plazo (Medium-Term Scheduler):
    • Se utiliza en sistemas con memoria virtual.
    • Puede "intercambiar" (swapping) procesos de la memoria principal al disco y viceversa para reducir el grado de multiprogramación o liberar memoria.
  • Planificador de E/S:
    • Decide el orden en que se tratan las solicitudes de E/S.

Algoritmos de Planificación de CPU

Estos algoritmos determinan qué proceso en la cola de listos se ejecutará a continuación en la CPU.

First-Come, First-Served (FCFS)

Es el algoritmo más sencillo. Los procesos se ejecutan en el orden en que llegan a la cola de listos. Se implementa con una cola FIFO (First-In, First-Out) y un Bloque de Control de Proceso (PCB) para cada uno. Es un algoritmo no expropiativo, lo que significa que un proceso conserva la CPU hasta que finaliza o realiza una operación de E/S. Puede ser problemático en sistemas de tiempo compartido debido a los largos intervalos de tiempo que un proceso puede monopolizar la CPU.

Shortest-Job-First (SJF)

Este algoritmo asocia a cada proceso la longitud de su próxima ráfaga de CPU. La CPU se asigna al proceso con la ráfaga más corta (en caso de empate, se puede usar FCFS). Se considera óptimo porque produce el tiempo de espera promedio mínimo para un conjunto dado de procesos. Sin embargo, es difícil de implementar en la práctica, ya que es imposible predecir con precisión la duración de la próxima ráfaga de CPU de un proceso.

Planificación por Prioridad

A cada proceso se le asigna un número de prioridad, y la CPU se asigna al proceso con la prioridad más alta. Los procesos con la misma prioridad se pueden planificar usando FCFS o SJF. Puede ser expropiativo (si un proceso de mayor prioridad llega, interrumpe al actual) o no expropiativo. Un problema común es el bloqueo indefinido (starvation), donde un proceso de baja prioridad nunca llega a ejecutarse si siempre hay procesos de mayor prioridad. Una solución es el envejecimiento (aging), que aumenta gradualmente la prioridad de los procesos que han esperado mucho tiempo.

Turno Rotatorio (Round Robin - RR)

Diseñado específicamente para sistemas de tiempo compartido. Es un algoritmo expropiativo similar a FCFS, pero con conmutación de contexto. Se define un pequeño intervalo de tiempo, llamado cuanto de tiempo (time quantum). Los procesos se colocan en una cola circular (implementación FIFO). La CPU se asigna al primer proceso de la cola por un tiempo máximo igual al cuanto. Si el proceso termina antes del cuanto, libera la CPU voluntariamente. Si no, el temporizador interrumpe al SO, y el proceso es movido al final de la cola de listos, permitiendo que el siguiente proceso se ejecute.

Sincronización de Procesos

Cuando múltiples procesos cooperan y comparten recursos (variables, comunicación), es crucial gestionar el acceso a la sección crítica. La sección crítica es la parte del código donde se accede a recursos compartidos. El objetivo es asegurar que solo un proceso a la vez pueda estar en su sección crítica, garantizando la exclusión mutua.

Para lograr una sincronización efectiva, se deben cumplir tres condiciones:

  • Exclusión Mutua: Si un proceso está ejecutando su sección crítica, ningún otro proceso puede ejecutar la suya.
  • Progreso: Si ningún proceso está en su sección crítica y algunos procesos desean entrar, solo aquellos que no están ejecutando su sección crítica pueden participar en la decisión de cuál entrará a continuación, y esta selección no puede posponerse indefinidamente.
  • Espera Limitada (Bounded Waiting): Existe un límite en el número de veces que otros procesos pueden entrar en sus secciones críticas después de que un proceso ha hecho una solicitud para entrar en su sección crítica y antes de que se le conceda esa solicitud.

Soluciones al Problema de la Sección Crítica

Se han propuesto varios algoritmos y soluciones para garantizar la exclusión mutua:

  • Alternancia Estricta (Algoritmo 1): Un enfoque simple pero ineficiente que alterna el turno entre dos procesos. Requiere que los procesos se turnen, incluso si uno no necesita entrar en su sección crítica.
  • Algoritmo 2 (con bandera): Cada proceso usa una bandera para indicar su deseo de entrar en la sección crítica. Puede llevar a un interbloqueo si ambos procesos establecen su bandera simultáneamente.
  • Algoritmo de Peterson: Una solución elegante para dos procesos que combina el uso de una variable de turno y un vector de banderas, satisfaciendo las tres condiciones de la sección crítica.
  • Algoritmo de la Panadería (Lamport): Una solución para múltiples procesos que asigna un "número de cliente" a cada proceso que desea entrar en la sección crítica. El proceso con el número más bajo entra primero, similar a una panadería.
  • Soluciones de Hardware:
    • Instrucción TestAndSet (Evaluar y Asignar): Una instrucción atómica que lee el valor de una variable y lo establece en verdadero en una sola operación indivisible.
    • Instrucción Swap (Intercambio): Una instrucción atómica que intercambia el contenido de dos variables.
    Estas instrucciones atómicas son fundamentales para construir mecanismos de sincronización más complejos como los semáforos.

Gestión de Memoria Principal

La gestión de memoria es crucial para la multiprogramación, permitiendo que múltiples procesos residan en memoria simultáneamente.

Asignación Contigua de Memoria

En este esquema, cada proceso se carga en un bloque contiguo de memoria. El Sistema Operativo reside en la parte baja de la memoria, y los procesos de usuario en la parte alta. Para proteger el SO y los procesos entre sí, se utilizan registros de reubicación (RR) y registros límite (RL). La dirección física se calcula sumando la dirección lógica al valor del registro de reubicación (Dirección Física = Dirección Lógica + RR). El planificador de CPU y el distribuidor de carga utilizan estos registros para cotejar y proteger los accesos a memoria.

Particionamiento Estático

Permite la multiprogramación dividiendo la memoria en particiones fijas. Cada partición puede contener un proceso. El grado de multiprogramación está limitado por el número de particiones. Este método es sencillo de implementar, pero puede ser ineficiente debido a la fragmentación interna (espacio no utilizado dentro de una partición si el proceso es más pequeño que la partición) y el desaprovechamiento de particiones desocupadas. Los algoritmos de asignación pueden ser de particiones de igual tamaño o de diferente tamaño, con colas separadas para cada tamaño o una única cola general.

Particionamiento Dinámico

En este esquema, las particiones no tienen un número ni un tamaño fijo. El SO mantiene una tabla de los bloques de memoria libres (huecos). Cuando un proceso llega, se le asigna un hueco de tamaño adecuado. Si el hueco es más grande que el proceso, el espacio restante se convierte en un nuevo hueco. Este método sufre de fragmentación externa (espacio libre total suficiente, pero no contiguo para un nuevo proceso). Para mitigar esto, los huecos adyacentes se fusionan cuando un proceso finaliza. Los algoritmos para seleccionar un hueco incluyen:

  • Primer Ajuste (First Fit): Asigna el primer hueco lo suficientemente grande que encuentra.
  • Mejor Ajuste (Best Fit): Asigna el hueco más pequeño que es lo suficientemente grande, dejando el hueco más pequeño posible.
  • Peor Ajuste (Worst Fit): Asigna el hueco más grande disponible, dejando un hueco grande para futuras asignaciones.

Sistema de Colegas (Buddy System)

Es un método de asignación de memoria que combina aspectos de particionamiento estático y dinámico. La memoria se divide recursivamente en bloques de tamaño potencia de 2 (2u). Cuando se solicita memoria, se busca el bloque más pequeño que sea lo suficientemente grande. Si no hay un bloque de ese tamaño, un bloque más grande se divide en dos "colegas" (buddies) de la mitad de su tamaño, y el proceso se repite hasta encontrar un bloque adecuado. Cuando un bloque se libera, se intenta fusionar con su colega si este también está libre, formando un bloque más grande.

Asignación No Contigua: Paginación

La paginación es un método de asignación no contigua donde el espacio de direcciones lógicas de un proceso se divide en bloques de tamaño fijo llamados páginas. La memoria física se divide en bloques del mismo tamaño llamados marcos de página (frames). Las páginas de un proceso pueden cargarse en cualquier marco de página disponible en la memoria física, sin necesidad de ser contiguas. Esto evita la fragmentación externa y reduce la fragmentación interna (solo el último marco de página puede desperdiciar espacio). El Sistema Operativo mantiene una Tabla de Páginas para cada proceso. Una dirección lógica se divide en un número de página (índice en la tabla de páginas) y un desplazamiento dentro de la página. La tabla de páginas contiene la dirección base del marco de página donde reside la página, y al sumarle el desplazamiento, se obtiene la dirección de memoria física (Dirección Física = Dirección Base del Marco + Desplazamiento).

Entradas relacionadas: