Presentación 1: Software Libre y Proyectos Fundamentales

Dentro de este software libre, tenemos algo que se llama las 4 libertades:

  • Usar el software.
  • Estudiar el software.
  • Distribuir el software.
  • Modificar el software.

La GPL (General Public License) es una de las licencias clave que garantizan las 4 libertades, asegurando que el código fuente esté disponible junto con el software y que las modificaciones deban ser redistribuidas bajo los mismos términos. Esto se hace para asegurar que el software libre permanezca libre siempre y no se vuelva privativo.

También existen otros tipos de licencias más permisivas como la MIT License o la BSD License, que permiten que el código sea modificado y cerrado.

Luego se habla de este tipo de licencias. Dentro de ellas, tenemos la diferencia entre software libre, software de código abierto y software propietario. Como dijimos, hay varios tipos de licencias, algunas más restrictivas, otras más permisivas.

Proyectos Destacados

Proyecto GNU

Después se habla del proyecto GNU, describiendo cómo este fue el precursor del movimiento del software libre, con el objetivo de crear un sistema operativo completamente libre. Richard Stallman fue el impulsor de la idea. El proyecto GNU comenzó con la creación de herramientas y utilidades como GCC y GNU Bash, que luego fueron complementadas con el kernel Linux, formando lo que hoy conocemos como GNU/Linux.

Proyecto Open Source (Código Abierto)

También se habla del proyecto Open Source (código abierto).

En este, se presenta un modelo más colaborativo, permitiendo la mejora continua del software a través del acceso al código fuente. Esta idea permite a los desarrolladores estudiar y mejorar softwares ya existentes. Ejemplos pueden ser Linux o Android, y empresas como Google o Red Hat.

Presentación 2: Introducción a los Sistemas Operativos

¿Qué es un Sistema Operativo?

Básicamente, es un conjunto de programas que actúan como intermediarios entre los usuarios y el hardware. Para proporcionar un entorno donde los programas se puedan ejecutar de manera eficiente, es conveniente administrar los recursos del hardware. Básicamente, coordina los recursos del sistema.

Roles del Sistema Operativo

Después se mencionan los dos roles principales del sistema operativo: como interfaz con el hardware y como administrador de recursos.

  • Interfaz con el hardware: El sistema operativo abstrae las complejidades del hardware para los usuarios y programas, permitiendo que los desarrolladores trabajen a un nivel más alto sin preocuparse por los detalles técnicos del hardware.
  • Administrador de recursos: El sistema operativo asigna eficientemente la CPU, la memoria y otros recursos a los programas que lo necesitan.

Ambos roles son esenciales para garantizar que las aplicaciones puedan ejecutarse simultáneamente, aprovechando al máximo los recursos del sistema.

Estructura Genérica de un Sistema Operativo

El kernel del S.O., que está cerca del hardware, proporciona los servicios esenciales de bajo nivel necesarios para la gestión de procesos, memoria y dispositivos de E/S (Entrada/Salida).

También se habla de que el modelo promueve la modularidad, permitiendo que los cambios en una capa no afecten a otras capas.

Servicios Básicos del Sistema Operativo

Algunos servicios básicos del sistema operativo son:

  • Ejecución de programas: Permite cargar y ejecutar programas.
  • Operaciones de entrada y salida: Gestiona dispositivos como discos y redes.
  • Manipulación del sistema de archivos: Permite crear, eliminar y manipular archivos o directorios.
  • Detección de errores: Monitorea el sistema para posibles fallos y garantiza su corrección.

El sistema operativo proporciona varios tipos de interfaces de usuario, siendo la CLI (Command Line Interface) una de las más antiguas y poderosas, permitiendo a los usuarios introducir comandos directamente al sistema para interactuar con él. Aunque verdaderamente está pensada para introducir comandos y no es tan intuitiva como la GUI (Graphical User Interface), la cual permite que los usuarios interactúen con el S.O. mediante iconos gráficos y no comandos mediante texto.

Presentación 3: Evolución Histórica de los Sistemas Operativos

Generación 0 (Mediados de los años 40)

En la generación 0, computadoras como la ENIAC no contaban con sistema operativo y se usaban como calculadoras para propósitos militares, funcionando con intervención manual.

Generación 1 (Años 50)

En la generación 1, aparece IBM, junto a varias universidades más, y empezaron a desarrollar rutinas de control en memoria para comenzar a estructurar lo que sería la primera generación de sistemas operativos. Se empezaron a desarrollar lenguajes ensambladores, permitiendo la automatización básica de tareas, pero seguían siendo sistemas muy rudimentarios.

Generación 2 (Finales de los 50 – Mediados de los 60)

En la generación 2 se inventa el transistor y se incrementa la memoria, lo que llevó a la necesidad de monitores básicos y rutinas de control para gestionar el hardware de manera más eficiente.

Generación 3 (Mediados de los 60 – Finales de los 70)

En la generación 3, se introduce el concepto de multiprogramación, donde varias tareas pueden ejecutarse simultáneamente, y aparece el IBM 360 con el primer sistema operativo. Trabajaban con punto fijo y flotante, con ideas tanto comerciales como científicas.

Después se explica que había una sola CPU que controlaba los periféricos, pero no podía manejar varios procesos en simultáneo, entonces tiene que requerir de otros mecanismos para permitir que varios procesos compartan la CPU.

Concurrencia

De ahí nace el concepto de concurrencia, donde la CPU alterna rápidamente entre diferentes procesos, lo que creaba la ilusión de que se estaban ejecutando al mismo tiempo.

Diagrama de Canales

Se menciona el diagrama de canales, donde el sistema operativo gestiona varios procesos simultáneamente e interactúa con los dispositivos de E/S a través de los canales. Los canales son vías de comunicación entre la CPU y los periféricos.

Este modelo permite que el S.O. sea eficiente al utilizar los canales de E/S para operaciones lentas mientras otros procesos continúan ejecutándose en la CPU, evitando pérdida de tiempo de procesamiento.

Presentación 4: Servicios y Funciones del Sistema Operativo

Primero se nos presenta la estructura de este y los componentes del sistema, que serían las principales responsabilidades de este.

Componentes y Responsabilidades Principales

  • Administración de procesos: El S.O. crea, programa, suspende y finaliza procesos, gestionando sus estados y asegurando que se ejecuten bien.
  • Administración de la memoria RAM: El S.O. gestiona la memoria principal, asignándola a procesos cuando lo necesitan y liberándola cuando finalizan. También gestiona la memoria virtual para expandir la capacidad de la RAM mediante el uso de espacio en el disco.
  • Administración del sistema E/S: Controla los dispositivos de entrada y salida (impresoras, discos, etc.), permitiendo que el sistema interactúe con estos recursos mediante controladores.
  • Administración de Almacenamiento secundario: Administra el almacenamiento a largo plazo, como discos duros, y organiza el acceso a archivos y directorios.
  • Operación en red: El S.O. permite la comunicación entre computadoras administrando redes y protocolos.
  • Sistema de protección: Garantiza que los procesos y usuarios no interfieran entre sí y que los recursos sean accesibles solo para usuarios con permisos.
  • Intérprete de comandos: El S.O. proporciona una interfaz para que el usuario interactúe con el sistema; puede ser las que mencionamos anteriormente, como CLI o GUI.

Proveedor de Servicios

El S.O. actúa como proveedor de servicios tanto para los usuarios como para los programas. Administra el hardware y facilita los programas para el usuario. Algunos servicios son:

  • Ejecución de Programas
  • Interfaz de Comunicación (Cómo nos comunicamos)
  • Operaciones de E/S
  • Manipulación del Sistema de Archivos
  • Comunicaciones
  • Detección de Errores
  • Asignación de Recursos
  • Contabilidad
  • Protección y Seguridad

Operaciones de E/S

Las operaciones de E/S las gestiona el S.O. y proporciona una interfaz para que los programas realicen operaciones de E/S sin tener que interactuar directamente con el hardware.

Manipulación de Archivos

El S.O. permite crear, modificar, leer y borrar archivos y directorios. También los organiza.

Asignación de Recursos

Otra función del S.O. en un sistema de multiprogramación es la asignación de recursos como la CPU y los dispositivos periféricos. Lleva un registro del uso de estos recursos para la contabilidad. Por lo tanto, el S.O. debe gestionarlos de manera eficiente. Para esto usa algoritmos de planificación o rutinas de planificación, asignando tiempo a los procesos.

Además de esto, el S.O. lleva registros detallados del uso de la CPU, la memoria y otros recursos. Estos datos pueden usarse para analizar el rendimiento del sistema o, en algunos casos, para fines comerciales.

System Calls (Llamadas al Sistema)

Estas básicamente son las interfaces entre los programas de usuario y el S.O. Estas llamadas permiten que las aplicaciones interactúen con los recursos del sistema.

Son programadas en lenguaje ensamblador; en Windows las llamamos API (Application Programming Interface).

En conclusión, son el mecanismo principal a través del cual un programa de usuario solicita servicios del S.O. Ejemplos podrían ser la creación y terminación de procesos, lectura y escritura de archivos, asignación de memoria y control de dispositivos. En Unix/Linux se utilizan a través de comandos como fork, exec, etc. En Windows, como dijimos antes, desde la API.

Estas llamadas al sistema se agrupan en 5 categorías:

  • Control de procesos: Incluye la creación, ejecución y terminación de procesos.
  • Manipulación de archivos: Permite acciones como crear, borrar, leer, escribir.
  • Manipulación de los dispositivos de E/S: Permite la interacción con estos dispositivos, como request (solicitud del dispositivo), release, open, close. En Linux se maneja diferente, ya que estos aparecen como archivos.
  • Mantenimiento de información: Permite la transferencia de datos entre el programa de usuario y el S.O. Básicamente, permite obtener información básica sobre el sistema, como la fecha, hora, información del S.O., cantidad de memoria libre.
  • Comunicaciones.

Modo Dual

Este modo garantiza la protección del S.O. mediante la implementación de dos modos de ejecución:

  • Modo supervisor (o kernel)
  • Modo usuario

Para gestionar estos modos se usa un bit de modo o bit de privilegio en el hardware del procesador para gestionar la distinción entre modo kernel (o supervisor) y modo usuario, donde el valor 0 indica que el sistema está en modo supervisor y el valor 1 indica que está en modo usuario.

Modo Usuario

Es el modo en el que se ejecutan las aplicaciones y programas regulares.

  • Tiene restricciones de acceso a recursos críticos del sistema, como el hardware y la memoria.
  • Las aplicaciones no pueden realizar directamente operaciones que afecten al hardware ni modificar directamente el sistema operativo.
  • Si un proceso necesita acceder a estos recursos, debe hacer una llamada al sistema (system call), que será gestionada por el sistema operativo desde el modo kernel.

Modo Kernel

Es el modo donde opera el sistema operativo y los procesos privilegiados.

  • Tiene acceso completo a todos los recursos del sistema, incluyendo el hardware.
  • En este modo, el sistema operativo gestiona las operaciones críticas, como la administración de memoria, la comunicación entre procesos y la interacción con los dispositivos de hardware.

En resumen, la principal diferencia es que el modo kernel tiene acceso total y sin restricciones al hardware y a las funciones críticas del sistema, mientras que el modo usuario tiene acceso limitado y debe solicitar al sistema operativo que realice las operaciones necesarias en su nombre.

Presentación 5: Diseño y Estructura de los Sistemas Operativos

Diseño y Estructura de los S.O.

Primero se nos presenta que un S.O. es un software que se diseña y desarrolla para cumplir ciertos propósitos. Y estos sistemas operativos se dividen en dos grandes ramas:

  • Sistemas operativos de propósito general
  • Sistemas operativos de propósito específico

Los sistemas operativos de propósito general son aquellos diseñados para soportar una variedad de aplicaciones en múltiples entornos. Por ejemplo, sistemas como Unix y Windows.

Los sistemas operativos de propósito específico son aquellos diseñados para necesidades específicas, como los sistemas operativos de tiempo real, que se dividen en tiempo real estricto y tiempo real no estricto. Ejemplos podrían ser sistemas de control industrial, sistemas médicos o dispositivos de seguridad. Básicamente, el funcionamiento correcto de este S.O. depende de la ejecución dentro de un lapso de tiempo determinado.

El diseño de los sistemas operativos de propósito específico se guía por los objetivos del diseño, que incluyen las políticas (qué hacer), los mecanismos (cómo hacerlo) y la implementación (cómo ejecutarlo).

Tipos de Sistemas Operativos

Estos son distintos enfoques de diseño y estructura:

Simple

Este tipo de diseño es caracterizado por la simplicidad en su estructura, con el S.O. siendo una colección de programas que corren en modo kernel (privilegios elevados) y proporcionan servicios básicos a las aplicaciones del usuario. Pero al estar diseñado para ofrecer la mayor funcionalidad con el menor espacio, y como no está dividido en módulos, el sistema no separa bien las interfaces y los niveles de funcionalidad, por eso es vulnerable a fallos.

Microkernel

En un microkernel, las funciones del S.O. se dividen en componentes más pequeños, lo que mejora la seguridad y la estabilidad del sistema. Solo las funciones más esenciales de tareas residen en el kernel. El resto de los servicios, como la gestión de archivos y drivers, se ejecutan en el espacio de usuario, comunicándose con el kernel a través de paso de mensajes.

Monolítico

Estos tienen todo su código en un único bloque; el kernel incluye todas las funciones del S.O., como la gestión de archivos, dispositivos, procesos, etc. Esto le da más eficiencia en términos de velocidad, pero posee una falta de flexibilidad, ya que es más difícil modificar o actualizar partes del sistema sin afectar al resto.

Por Capas

Divide el S.O. en niveles o capas. Cada capa proporciona funciones a la capa superior y depende de la capa inferior para obtener ciertos servicios. El hardware está en la capa más baja, la interfaz de usuario en la más alta. Esta organización facilita la depuración y el mantenimiento, pero puede agregar sobrecarga debido al paso de datos entre capas.

Modular

Este es similar al microkernel en que las funciones del S.O. están divididas, pero con menos sobrecarga, ya que no depende del paso de mensajes para la comunicación entre módulos. Este diseño proporciona flexibilidad, ya que permite añadir o eliminar funcionalidades según sea necesario.

Máquinas Virtuales

Se presenta el concepto de virtualización, que permite la ejecución de varios sistemas operativos en una única máquina física, utilizando software que emula hardware. Esto nos permite asignar y gestionar dinámicamente los recursos del sistema, mejorando la eficiencia y el uso de recursos. A cada máquina virtual se le pueden asignar recursos como CPU, memoria y almacenamiento de manera dinámica, ajustando los recursos según las necesidades de cada sistema.

Docker

Docker es una plataforma de contenedores que permite empaquetar aplicaciones y sus dependencias en un entorno portable. Los contenedores son ligeros y portátiles, permitiendo que las aplicaciones se ejecuten en cualquier máquina que tenga Docker instalado. A diferencia de las máquinas virtuales, no necesitan ejecutar un S.O. completo. Por eso son más eficientes en cuanto a recursos y más ligeros en términos de consumo de espacio.

Modelo Cliente-Servidor

Otro modelo que vemos es el modelo cliente-servidor, en el que los clientes solicitan servicios o recursos a un servidor, que proporciona las respuestas o realiza las tareas necesarias.

Entornos Informáticos

Se describen entornos informáticos como el tradicional, P2P (entre iguales) y los sistemas web.

  • Sistemas Tradicionales: Involucran servidores dedicados y clientes que acceden a recursos de forma local o remota, generalmente LAN o WAN.
  • Sistemas P2P (Peer-to-Peer): En este tipo de sistemas, no hay una distinción clara entre clientes y servidores; cada nodo puede actuar como ambos, lo que permite compartir recursos directamente entre usuarios, como en aplicaciones de intercambio de archivos.
  • Sistemas Web: Estos sistemas permiten a los usuarios acceder a servicios y aplicaciones a través de navegadores web, sin necesidad de software especializado.

Interrupciones

Una interrupción en un S.O. es una suspensión temporal de un proceso para ejecutar una subrutina de interrupción. Estas subrutinas suelen pertenecer al S.O. o al BIOS. Una vez finalizada, se reanuda la ejecución del proceso original.

Cuando se produce una interrupción, la CPU detiene la ejecución en curso, guarda el estado del PC (Contador de Programa) y otros registros, luego salta a la dirección de la rutina de servicio de interrupción (ISR – Interrupt Service Routine). Una vez finalizada la rutina, es decir, que el ISR ha hecho su trabajo, se restauran los valores y se reanuda el proceso interrumpido.

También hay tipos de interrupciones:

  • Interrupciones de Hardware: Causadas por cualquier dispositivo que interrumpe, como una tecla presionada o el disco rígido.
  • Interrupciones de Software: Por ejemplo, la finalización de un pedido que solicitó el S.O. para procesar información.
  • Excepciones: Comúnmente errores, como dividir por cero, por ejemplo.

Presentación 6: Multiprogramación, Procesos y Planificación Inicial

Multiprogramación

Se introduce el concepto de multiprogramación, un concepto que se originó en los años 60 para permitir la ejecución de procesos en paralelo o concurrentemente.

  • Concurrencia: Simulación de múltiples procesos en una sola CPU mediante el cambio rápido de contexto entre ellos.
  • Paralelismo: Ejecución simultánea real de múltiples procesos en sistemas con múltiples CPUs o núcleos. (Los núcleos, en el contexto de los sistemas operativos y los procesadores, se refieren a las unidades de procesamiento independientes dentro de un procesador físico).

Diagrama de 5 Estados del Ciclo de un Proceso

Nodos (Estados)

  • Nuevo: Este es el estado inicial de un proceso cuando se ha creado, pero aún no está listo para ejecutarse. En este estado, el proceso ha sido iniciado por una llamada a la función fork().
  • Listo: El proceso está en memoria principal y listo para ser ejecutado, pero aún no ha sido asignado a la CPU. Está esperando su turno para ser despachado y ejecutado. Este es un estado de espera activa.
  • Ejecutando (Exec): El proceso está siendo ejecutado actualmente por la CPU. En este estado, el proceso está utilizando la CPU para realizar sus operaciones.
  • Espera: El proceso está esperando la finalización de alguna operación de entrada/salida (E/S), como la lectura de disco, acceso a la impresora o la red. Está en una espera pasiva hasta que se complete la E/S.
  • Fin: Este es el estado final del proceso, cuando ha terminado su ejecución. El proceso ha sido eliminado de la memoria y todos sus recursos han sido liberados.

Aristas (Transiciones)

  • Llamada a fork() (Nuevo → Listo): Esta es la transición cuando un nuevo proceso es creado mediante una llamada al sistema fork(). El proceso se coloca en el estado de Listo esperando ser ejecutado.
  • Despachador (Listo → Exec): Esta transición es gestionada por el despachador del sistema operativo, que asigna la CPU al proceso que está en el estado de Listo. El proceso comienza a ejecutarse.
  • Interrupción Interna (Exec → Listo): Ocurre cuando el proceso es interrumpido por la propia CPU debido a que su tiempo de uso de la CPU ha terminado (normalmente controlado por el temporizador del sistema). El proceso regresa al estado de Listo para esperar otro turno de ejecución.
  • Interrupción Externa (Exec → Espera): Esta transición ocurre cuando el proceso solicita una operación de entrada/salida, como leer un archivo o enviar datos a una impresora. El proceso se mueve al estado de Espera hasta que la operación de E/S se complete.
  • System Call (Espera → Listo): Después de que el proceso completa una operación de E/S, vuelve al estado de Listo, esperando nuevamente ser ejecutado. Esto es gestionado por una llamada del sistema (System Call).
  • Llamada a end() (Exec → Fin): Esta transición ocurre cuando el proceso termina su ejecución. La llamada a end() indica que el proceso ha finalizado y es eliminado del sistema, liberando todos sus recursos.

PCB (Bloque de Control de Proceso)

La información de cada proceso está contenida en una estructura denominada PCB (Process Control Block). Esta almacena datos esenciales para gestionar y controlar un proceso en el S.O.

El PCB contiene información esencial de cada proceso como:

  • Estado del proceso (ejecución, listo, espera).
  • Contador de programa (señala la próxima instrucción a ejecutar del proceso).
  • Registros de la CPU (incluye el estado de los registros del procesador, lo cual debe guardarse y restaurarse en los cambios de contexto).
  • Información de planificación (detalles como la prioridad del proceso y su posición en las colas de planificación).
  • Información de administración de memoria (como las tablas de páginas o límites de memoria).

Cambio de Contexto

Un cambio de contexto es el proceso en el cual el sistema operativo guarda el estado de un proceso en ejecución para poder restaurarlo más adelante, permitiendo que otro proceso utilice la CPU.

Tipos de Planificadores

Existen tres tipos de planificadores que seleccionan los procesos en las distintas colas:

  • Planificador de Largo Plazo: Controla el número de procesos que se mantienen en memoria, asegurando un equilibrio entre procesos de entrada/salida y aquellos que usan intensamente la CPU.
  • Planificador de Mediano Plazo: Implementa mecanismos de swapping, retirando procesos de la memoria temporalmente para optimizar el uso de recursos del sistema.
  • Planificador de Corto Plazo: Es responsable de asignar la CPU a un proceso listo para ejecución, por lo que su ejecución debe ser rápida y eficiente.

Procesos Independientes y Cooperativos

  • Los procesos independientes no se ven afectados por otros procesos en ejecución.
  • Los procesos cooperativos pueden ser afectados por otros procesos, compartiendo información entre sí. Para comunicarse, los procesos cooperativos pueden utilizar pasaje de mensajes o memoria compartida.

Creación de Procesos con fork()

La función fork() se usa para crear un nuevo proceso; este proceso es denominado hijo, mientras que el proceso original que invoca fork() es el padre.

Al invocar fork(), el S.O. crea un nuevo proceso hijo que es una copia casi exacta del proceso padre. Sin embargo, aunque ambos se crean a partir del mismo espacio de memoria, una vez creado el hijo, cada proceso ejecuta de manera independiente, lo que significa que las variables pueden tener valores diferentes en el padre y el hijo a medida que avanzan sus ejecuciones.

Retorno de fork(): Al padre se le retorna el valor del PID (Process Identifier) del hijo, y al hijo se le retorna 0.

Si hay algún problema en la creación del hijo, devuelve el valor -1 y no se crea ningún proceso.

Conclusión: La función fork() es crucial para la creación de procesos en sistemas operativos tipo UNIX, ya que permite que los procesos se dupliquen de manera eficiente, manteniendo sus propias ejecuciones y modificando sus espacios de memoria de forma independiente.

Presentación 7: Hilos y Modelos de Hilos

Hilos (Threads)

Un hilo es una entidad dinámica, también conocida como subproceso.

Son unidades más pequeñas dentro de los procesos. Antes solo existía un hilo de ejecución en sistemas con una sola CPU.

Este se puede ejecutar de manera independiente, comparte recursos del proceso (como la memoria y archivos abiertos), pero tiene su propio contador de programa, pila y registros. Esto permite que un proceso realice múltiples tareas simultáneamente.

Beneficios de programar con hilos:

  • Grado de respuesta: Al usar hilos, el programa puede responder más rápido, ya que diferentes hilos pueden ejecutarse en diferentes núcleos de la CPU.
  • Compartir recursos: Los hilos comparten los mismos recursos del proceso que los genera, lo que permite una mayor eficiencia en el uso de la memoria.
  • Economía: Se ahorra en el uso de la memoria y recursos, ya que los hilos comparten el mismo espacio de direcciones.
  • Utilización de arquitecturas multinúcleo: Los hilos permiten aprovechar al máximo las arquitecturas de sistemas con múltiples núcleos de procesamiento.

Hilos y PCB: El TCB (Thread Control Block)

Antes habíamos dicho que la PCB mantiene la información sobre cada proceso. Y como dijimos que un proceso está conformado por hilos, por lo tanto, dentro de cada PCB vamos a tener pequeñas unidades llamadas TCB (Thread Control Block), que es un subcomponente del PCB. Cada TCB incluye información específica de cada hilo, como el ID del hilo (tid), el puntero de instrucción (ip), los registros y la pila.

Modelo Uno a Uno

En este modelo (de los años 80), cada vez que un hilo del usuario es creado, el S.O. crea un hilo correspondiente a nivel del kernel. Este modelo permite una ejecución paralela de hilos en diferentes CPUs, aprovechando el hardware multinúcleo.

Ventaja: Como se pueden ejecutar los hilos en paralelo en diferentes núcleos del procesador, incrementa la eficiencia y la velocidad del sistema.

Desventaja: Consume muchos recursos, ya que cada hilo de usuario necesita su propio hilo en el kernel, lo cual aumenta la sobrecarga del S.O.

Presentación 8: Planificación Avanzada de CPU y Algoritmos

Conceptos Avanzados de Multiprogramación

La multiprogramación es una técnica donde varios programas o procesos están en memoria principal a la vez y compiten por acceder a la CPU. El sistema operativo se encarga de gestionar esta competencia mediante la planificación de la CPU, eligiendo qué proceso utiliza el procesador en cada momento.

Entonces, de la multiprogramación vamos a tener el uso compartido de la CPU entre múltiples procesos/hilos.

Vamos a tener dos tipos de procesos:

  • Procesos Orientados a la CPU: Estos procesos consumen más tiempo, ya que realizan muchas operaciones internas y cálculos; por eso se dice que tienen ráfagas largas de ejecución.
  • Procesos Orientados a E/S: Suelen esperar la entrada o salida de dispositivos periféricos; se dice que tienen ráfagas cortas, ya que estos procesos no requieren utilizar la CPU durante largos periodos, sino que pasan la mayor parte de su tiempo esperando operaciones de entrada/salida (E/S).
  • Procesos Intermedios.

Otro objetivo de la multiprogramación es lograr el máximo uso de la CPU. Para eso, el sistema debe planificar adecuadamente los procesos para que, mientras unos esperan por E/S, otros puedan aprovechar el tiempo de CPU disponible.

Planificación con Desalojo (Preemptive) y sin Desalojo (Non-Preemptive)

En la planificación con desalojo, el S.O. puede interrumpir un proceso en ejecución para asignar la CPU a otro proceso con mayor prioridad. Esto asegura que los procesos importantes o urgentes reciban más atención del procesador.

En la planificación sin desalojo, una vez que ha comenzado a ejecutarse un proceso, no será interrumpido hasta que termine su ejecución o realice una operación de E/S. Este enfoque es menos flexible pero más sencillo de implementar y garantiza que los procesos finalicen sin interrupciones.

Diagrama de 9 Estados de Unix

Unix maneja los procesos a través de múltiples estados que reflejan las diferentes fases de vida de un proceso. Los estados van desde “nuevo”, cuando el proceso está siendo creado, hasta “zombie”, cuando ha finalizado pero su entrada aún no ha sido limpiada por el sistema. Los eventos como llamadas al sistema, interrupciones o falta de memoria pueden causar transiciones entre estos estados.

Algoritmos de Planificación

Conceptos: Apropiativo vs. No Apropiativo

Un algoritmo de planificación no apropiativo (o no expropiativo) significa que, una vez que un proceso ha sido asignado a la CPU, no puede ser interrumpido hasta que termine su ejecución o llegue a un estado en el que no necesite más la CPU.

Algoritmo FCFS (First-Come, First-Served)

En el algoritmo FCFS, los procesos se ejecutan en el orden en que llegan y consumen unidades de tiempo de CPU. Es un algoritmo fácil de implementar, pero puede causar que los tiempos de espera y la secuencia de ejecución sean largos, lo que puede generar penalización para algunos procesos si tienen que esperar por otros más largos.

Variantes de FCFS: No Apropiativa y Apropiativa

En la variante no apropiativa de FCFS, cuando un proceso obtiene la CPU, no puede ser interrumpido hasta que termine su ejecución. Es decir, el proceso debe completar su ejecución antes de que la CPU sea asignada a otro proceso, incluso si llegan otros procesos de mayor prioridad o que necesiten menos tiempo de CPU.

En la variante apropiativa, un proceso que está ejecutándose puede ser interrumpido y la CPU puede ser reasignada a otro proceso. Aunque este comportamiento no es típico en un algoritmo FCFS puro, algunos sistemas pueden incluir características de apropiación si se combinan con otras políticas de planificación.

Algoritmo SJF (Shortest Job First)

Este algoritmo es óptimo en términos de tiempo de espera, ya que ejecuta primero los trabajos más cortos. Pero, por otro lado, tarda tiempo en reconocer o estimar el tiempo de ejecución de cada proceso. Existen dos tipos:

  • No apropiativo: Una vez que el proceso empezó a ejecutarse, no puede ser interrumpido.
  • Apropiativo: Permite que un proceso sea interrumpido si llega otro con un tiempo de ejecución menor.

Algoritmo SRTF (Shortest Remaining Time First)

Este algoritmo es una variante del algoritmo SJF, pero con una diferencia clave: es preemptive (apropiativo), lo que significa que puede interrumpir la ejecución de un proceso si otro proceso con un tiempo de CPU restante más corto entra en la cola de listos. El algoritmo SRTF es útil cuando se busca minimizar el tiempo de espera promedio en el sistema. Aunque es un algoritmo eficiente en términos de tiempo de espera promedio, su implementación genera muchas interrupciones y cambios de contexto, lo que puede aumentar la sobrecarga (overhead) del sistema.

Algoritmo de Planificación por Prioridades

Este tipo de planificación asigna una prioridad a cada proceso, y el sistema operativo selecciona para ejecución el proceso con la mayor prioridad. La prioridad puede ser apropiativa o no apropiativa. En un sistema apropiativo, si un nuevo proceso llega con una prioridad mayor que el proceso en ejecución, el sistema interrumpe el proceso actual para ejecutar el nuevo. En sistemas no apropiativos (non-preemptive), el proceso en ejecución no es interrumpido.

Un problema de este tipo de planificación es la inanición, donde un proceso de baja prioridad puede nunca ejecutarse si hay un flujo constante de procesos de alta prioridad. Esto puede ser mitigado con técnicas como el aging (envejecimiento), donde la prioridad de un proceso aumenta a medida que pasa tiempo en la cola de espera. Este tipo de planificación es útil para sistemas en tiempo real donde algunos procesos necesitan ser atendidos de manera urgente.

Algoritmo Round Robin (RR)

Es eficiente para sistemas interactivos donde es importante la respuesta rápida. El algoritmo Round Robin (RR) es uno de los más utilizados en sistemas operativos por su simplicidad y eficiencia al repartir el tiempo de CPU entre varios procesos. En este esquema, los procesos se colocan en una cola circular y se les asigna un quantum, que es una pequeña cantidad de tiempo en la que cada proceso se puede ejecutar. Si el proceso no finaliza en ese tiempo, se coloca al final de la cola y el siguiente proceso toma control de la CPU. Este sistema garantiza equidad, ya que cada proceso recibe el mismo tiempo de ejecución. No obstante, puede ser ineficiente para procesos orientados a CPU. Los procesos orientados a CPU que requieren largas ráfagas de ejecución pueden verse perjudicados, ya que constantemente serán interrumpidos para ceder el tiempo a otros procesos, lo cual puede aumentar su tiempo de respuesta.

Variante de Round Robin en el Kernel Linux

Esta variante utiliza una doble cola y memoria de lo utilizado previamente, lo que permite mejorar la eficiencia en la asignación del tiempo de CPU. Los procesos se alternan entre dos colas, una activa y otra pasiva, lo que permite gestionar mejor la carga de trabajo y evita que procesos con menos demanda de CPU sean relegados indefinidamente. También define un quantum grande, lo que reduce la frecuencia de cambios de contexto.

Algoritmo de Colas Multinivel (Multicola)

La planificación por colas multinivel permite agrupar procesos según sus características o necesidades de ejecución. Cada cola tiene su propia política de planificación, que puede variar entre un algoritmo FCFS o de Round Robin. Los procesos interactivos, por ejemplo, requieren respuestas rápidas y son asignados a colas con prioridad alta, mientras que los procesos por lotes o de usuario, que no tienen urgencia, son asignados a colas de menor prioridad. Esto es vital para garantizar la estabilidad y eficiencia del sistema operativo.

Colas Multinivel con Retroalimentación

Este algoritmo tiene retroalimentación. La retroalimentación en colas multinivel es una mejora a la planificación de colas fijas, donde los procesos se mueven entre colas dependiendo de su comportamiento. Este enfoque permite al sistema ser más flexible y adaptarse mejor a las necesidades de los procesos: los procesos que consumen más tiempo de CPU (por ejemplo, procesos con ráfagas largas) pueden ser movidos a colas de menor prioridad, dejando la CPU libre para procesos interactivos que requieren respuestas rápidas.

Presentación 9: Comunicación y Sincronización Entre Procesos (IPC)

Introducción a la Comunicación Entre Procesos (IPC)

La IPC (Inter-Process Communication) es la comunicación entre procesos. Sirve para compartir información, acelerar el cálculo, modularidad y conveniencia. En la comunicación directa, los procesos deben nombrarse explícitamente entre ellos para enviar y recibir mensajes, lo que puede complicar el diseño del sistema operativo. En contraste, la comunicación indirecta utiliza recursos compartidos como colas de mensajes o espacios de memoria, donde los mensajes se depositan y luego son recogidos por el receptor, facilitando la desvinculación de los procesos y la flexibilidad en la comunicación.

Comunicación Directa

Enlace directo entre dos procesos; el emisor y receptor deben estar identificados.

  • Sincrónica: Ambos procesos se nombran y esperan.
  • Asincrónica: Solo el emisor nombra al receptor.

Comunicación Indirecta

Comunicación a través de un buzón o puerto compartido entre procesos.

  • Unívoco: Un buzón entre dos procesos.
  • Multívoco: Un buzón compartido entre varios procesos.

Modelos Principales de IPC

Hay dos modelos principales de IPC: Memoria Compartida y Pasaje de Mensajes.

  • Pasaje de Mensajes: Método que permite que los procesos se comuniquen mediante el envío y recepción de mensajes. Son útiles en sistemas distribuidos donde los procesos pueden estar ejecutándose en diferentes máquinas.
  • Memoria Compartida: Permite que varios procesos accedan a un mismo bloque de memoria. Los procesos tienen una comunicación más rápida pero requiere una adecuada sincronización.

Enlace de Comunicación

El enlace entre procesos se establece automáticamente por el sistema operativo, y este enlace solo se forma entre un par de procesos. No es compartido ni reutilizado por otros procesos. Generalmente, este tipo de enlace es bidireccional, permitiendo el intercambio de mensajes en ambos sentidos, aunque también puede configurarse para ser unidireccional.

Sincronización en IPC

Tanto en la comunicación directa como en la indirecta, los procesos pueden usar mecanismos de sincronización bloqueante o no bloqueante dependiendo del diseño del sistema operativo y las necesidades del proceso.

En la comunicación directa, la sincronización es más explícita, ya que los procesos se envían y reciben mensajes nombrándose mutuamente. El modelo de sincronización bloqueante es útil en sistemas que requieren alta coordinación entre los procesos.

En la comunicación indirecta (usando buzones), el modelo de sincronización no bloqueante puede ser más eficiente, especialmente si múltiples procesos están compartiendo el mismo buzón y no es necesario que el emisor espere a que todos reciban el mensaje.

Se explica que el envío y recepción de mensajes puede ser bloqueante (síncrono) o no bloqueante (asíncrono), lo que afecta la forma en que los procesos se sincronizan al intercambiar información.

Buffering (Almacenamiento en Cola)

El buffering o almacenamiento en cola es una técnica crucial para gestionar la comunicación entre procesos (IPC). Según el libro, existen diferentes capacidades para las colas, las cuales determinan cómo se manejan los mensajes en el sistema de comunicación:

  • Capacidad Cero (Zero capacity): No se pueden almacenar mensajes en la cola, por lo que el remitente debe esperar hasta que el receptor esté listo (rendezvous).
  • Capacidad Limitada (Bounded capacity): La cola tiene una capacidad finita, es decir, solo se pueden almacenar un número limitado de mensajes. El remitente deberá esperar si la cola está llena.
  • Capacidad Ilimitada (Unbounded capacity): La cola tiene capacidad infinita (en teoría), lo que permite que el remitente nunca tenga que esperar, ya que siempre hay espacio para almacenar más mensajes.

Implementaciones de IPC: POSIX y Windows

El libro explica que los sistemas POSIX y Windows implementan IPC de diferentes maneras, aunque ambos tienen el objetivo común de facilitar la comunicación entre procesos. En sistemas basados en POSIX, como Unix y Linux, el uso de pipes es fundamental para la interacción entre comandos de línea. Estos sistemas proporcionan un entorno en el que las aplicaciones pueden interactuar de manera fluida mediante flujos de datos.

Por otro lado, el sistema de Windows implementa un modelo más complejo con el uso de RPC (Remote Procedure Calls), permitiendo que los procesos locales y remotos intercambien datos de manera eficiente. Este modelo está especialmente diseñado para entornos distribuidos, donde los procesos pueden estar en diferentes máquinas, pero actúan como si estuvieran en el mismo sistema.

Formas de Comunicación en Arquitecturas Cliente-Servidor

Después se nos describen tres formas de comunicación utilizadas en sistemas de arquitectura cliente-servidor, que permiten la interacción entre procesos distribuidos o en diferentes partes de un sistema.

  1. Sockets: Es un método estándar para habilitar la comunicación entre procesos que pueden estar en máquinas diferentes o en la misma máquina. A través de los sockets, los procesos pueden enviar y recibir datos utilizando protocolos como TCP/IP. El libro describe los sockets como el mecanismo de comunicación más fundamental y común entre procesos distribuidos. Los sockets permiten a los procesos establecer una conexión usando direcciones IP y puertos, y su funcionamiento depende de una pila de protocolos de red subyacente.

    Un socket representa un extremo de la comunicación, y su operación es transparente, lo que significa que no importa si el otro proceso está en la misma máquina o en una remota. El libro también menciona la importancia de usar puertos para identificar aplicaciones; hay una distinción entre los puertos públicos (comúnmente por encima del número 1024) y los privados, que se suelen reservar para usos específicos.

  2. Remote Procedure Calls (RPC): Es una técnica que permite que un proceso solicite la ejecución de un procedimiento en otro proceso, incluso si este último se encuentra en una máquina remota. Windows utiliza este modelo para la comunicación dentro de sus propios procesos, empleando el concepto cliente-servidor.

  3. Remote Method Invocation (RMI – Java): Similar a RPC, pero específico de Java, donde un método de un objeto puede ser invocado desde otro objeto ubicado en una máquina remota. Esto se utiliza para la comunicación entre objetos distribuidos en la red.

El Problema de la Sincronización

En todos estos sistemas surge un problema que los sistemas monoproceso no tienen: la sincronización. Se presentan los conceptos básicos de la sincronización de procesos, resaltando la importancia de cómo los procesos comparten recursos y cómo esto puede llevar a problemas de sincronización si no se gestionan correctamente. Esto suele pasar en casos de ejecución en procesos concurrentes, como procesos que corren en multi-CPU, o sea, que corren en paralelo.

Un recurso compartido puede ser una variable global. Hay que tener cuidado con esto por la condición de carrera. El libro detalla cómo las condiciones de carrera surgen cuando varios procesos o hilos acceden simultáneamente a datos compartidos sin la adecuada sincronización.

La condición de carrera es un problema serio, un caso muy común en programación concurrente, en donde un recurso es accedido por más de un proceso; comparten un recurso determinado. Para evitar este problema, lo que hacemos es lo siguiente: agarramos una porción del código que accede a un recurso compartido el cual se puede modificar y, cuando un proceso esté en la sección crítica (puede haber más de un proceso), ningún otro proceso puede acceder a esa sección. A eso lo denominamos sección crítica. Existen varias soluciones a este problema. Primero y principal, tenemos algunas condiciones que nuestro sistema debe tener o cumplir para proponer una solución al problema de la sección crítica:

  • Debemos definir un protocolo: reglas o mecanismos que se establecen para controlar el acceso concurrente de múltiples procesos a una porción de código donde se manipulan recursos compartidos.
  • Debemos saber si estamos en sistemas Mono-CPU o Múltiple-CPU.

Una problemática de esto es que en un algoritmo de prioridad, esto no tiene sentido (según Silberschatz).

Exclusión Mutua (Mutex)

De acá sale un concepto que se llama Exclusión Mutua o mutex.

Un solo proceso puede estar en la sección crítica. Entonces, cuando nosotros establecemos un protocolo, lo que estamos haciendo es un cerrojo.

En un algoritmo de prioridad podríamos tener un problema de inanición.

Encima, incluso en un algoritmo de prioridad, se puede sumar otro proceso a usar ese recurso. Entonces, para evitar este problema se deberían establecer estas dos reglas:

  • Progreso (Silberschatz): Solo participan los procesos que están en la cola (no los que están en la sección restante). No pueden participar otros procesos que están en actividades preliminares.
  • Espera Limitada (Silberschatz): Ningún proceso puede esperar ilimitadamente la entrada a la sección crítica.

También existen varias soluciones a este problema, como el algoritmo de Peterson, una solución por software que usa un contador y unas banderas; pero pasa que ese algoritmo no funciona hoy en día, porque tenemos multi-CPU (no hace falta estudiar esto).

También hay soluciones por hardware como el test-and-set, que no se usa mucho porque no permite interrupciones.

Índice de Contenidos por Hojas

Hoja 1

  • Presentación 1: 4 libertades, licencias, proyectos.
  • Presentación 2 (Parte 1): ¿Qué es un S.O.?

Hoja 2

  • Presentación 2 (Parte 2): Roles del S.O., estructura genérica, servicios básicos.

Hoja 3

  • Presentación 3: Generaciones, concurrencia, Diagrama de canales.

Hoja 4

  • Presentación 4 (Parte 1): Servicios del S.O., proveedor de servicios.

Hoja 5

  • Presentación 4 (Parte 2): Las operaciones de E/S, la manipulación de archivos, asignación de recursos, System Calls.

Hoja 6

  • Presentación 4 (Parte 3): Modo dual.

Hoja 7

  • Presentación 5 (Parte 1): Diseño y estructura de los S.O., tipos de sistemas operativos (Parte 1).

Hoja 8

  • Presentación 5 (Parte 2): Tipos de sistemas operativos (Parte 2), máquinas virtuales, Docker.

Hoja 9

  • Presentación 5 (Parte 3): Entornos informáticos, interrupción.
  • Presentación 6 (Parte 1): Multiprogramación (concurrencia y paralelismo).

Hoja 10

  • Presentación 6 (Parte 2): Diagrama de 5 estados (Parte 1).

Hoja 11

  • Presentación 6 (Parte 3): Diagrama de 5 estados (Parte 2), PCB, Cambio de contexto.

Hoja 12

  • Presentación 6 (Parte 4): Tipos de planificadores, procesos independientes y cooperativos, crear procesos con fork.

Hoja 13

  • Presentación 7: Hilos, hilos y PCB (TCB), modelos de hilos.

Hoja 14

  • Presentación 8 (Parte 1): Multiprogramación (Parte 2), planificación con desalojo y sin desalojo, diagrama de 9 estados de Unix.

Hoja 15

  • Presentación 8 (Parte 2): Algoritmos apropiativos y no apropiativos, algoritmos de planificación (FCFS, SJF, SRTF).

Hoja 16

  • Presentación 8 (Parte 3): Algoritmo de prioridades, Round Robin y variante.

Hoja 17

  • Presentación 8 (Parte 4): Algoritmo multicola.
  • Presentación 9 (Parte 1): Comunicación directa e indirecta.

Hoja 18

  • Presentación 9 (Parte 2): Memoria compartida y pasaje de mensajes, enlace, sincronización para comunicación.

Hoja 19

  • Presentación 9 (Parte 3): Buffering.

Hoja 20

  • Presentación 9 (Parte 4): Sockets.

Hoja 21

  • Presentación 9 (Parte 5): Sincronización y problemáticas.

Hoja 22

  • Presentación 9 (Parte 6): Problemáticas (continuación).