Está en la página 1de 30

INDICE

Tema 1: Conceptos generales …………………………………………………………………………………............. 2


1.1 ¿Qué es un sistema operativo? ………………………………………………………………………………………… 2
1.1.1 El SO como interfaz ……………………………………………………………………………………………………. 2
1.1.2 El SO como administrador de recursos ………………………………………………………………………. 3
1.1.3 Grandes logros del sistema operativo ………………………………………………………………………... 3
1.1.4 Algunos tipos de sistemas ……………………………………………………………………………………….... 5
1.2 Estructura del computador y SO ……………………………………………………………………………….……… 6
1.2.1 Estructura de la E/S …………………………………………………………………………………………….…… 6
1.2.2 Sistema de interrupciones ………………………………………………………………………………………. 7
1.2.3 Jerarquía de memorias ………………………………………………………………………………………….… 7
1.2.4 Protección del hardware …………………………………………………………………………………….…… 8
1.3 Estructura del sistema operativo ……………………………………………………………………………........... 9
1.3.1 Componentes del S.O. …………………………………………………………………………………………….. 9
1.3.2 Arquitecturas para los S.O. ………………………………………………………………………………………. 10

Tema 2: Procesos ……………………………………………………………………………………………………………… 13


2.1 Procesos e hilos ……………………………………………………………………………………………………….…….. 13
2.1.1 Procesos ………………………………………………………………………………………………………………….. 13
2.1.2 Hilos (threads) …………………………………………………………………………………………………………. 16
2.2 Algoritmos de planificación de CPU ………………………………………………………………………….…….. 17

Tema 3: Concurrencia ……………………………………………………………………………………………………….. 21


3.1 Programación concurrente ………………………………………………………………………………………….. 21
3.2 El problema de la sección crítica ………………………………………………………………………………….. 22
3.3 Mutex (cerrojos) y variables condición ……………………………………………………………………….. 25
3.4 Sincronización ……………………………………………………………………………………………………………. 26
3.5 Problemas clásicos de sincronización ………………………………………………………………………….. 29

Tema 4: Memoria……………………………………………………………………………………………………..
4.1 Gestión de memoria……………………………………………………………………………………………………..
4.2 Memoria virtual……………………………………………………………………………………………………..

Tema 5: Archivos……………………………………………………………………………………………………..

1
Tema 1. Conceptos generales
1.1 ¿Qué es un sistema operativo?
– Es un programa que actúa de intermediario entre los usuarios y el hardware.
– Un sistema de software cuyo fin es que un sistema informático sea operativo, es decir,
facilita el uso del sistema al usuario.
– Conjunto de programas que gestionan los recursos del sistema, optimizan su uso y resuelven
conflictos.
– Pertenece al software del sistema.

• El sistema operativo se relaciona con el:


– Hardware (Procesador y memoria, Dispositivos de E/S: almacenamiento, red, HCI,
impresión, etc.).
– Software (Software de sistema: compilador, GUI, shell, Aplicaciones, etc.).
– Personas (Usuarios en general, Administradores del sistema, desarrolladores
/programadores).

Objetivos del SO:

– Proveer un entorno para ejecutar las aplicaciones.


– Administrar eficientemente los recursos.
– Facilitar la interacción con el computador.
– Facilitar la evolución del software y del hardware.

Los dos roles del SO:

• Interfaz con el hardware


– Añade características no existentes en el hw.
– Oculta características inconvenientes del hw.
– Ofrece una «máquina extendida».

• Administrador de recursos
– Como si fuera un «gobierno del hardware».
– Concede recursos de forma segura, justa y eficiente.
– No realiza trabajo productivo.

El SO como interfaz
• Visión: una «capa» que envuelve el hardware y ofrece una «máquina abstracta» con otras
características:
– Oculta detalles incómodos del hardware.
– Amplía características no presentes en el hardware.
• La interfaz se desarrolla para Usuarios, Administradores y Desarrolladores.

• ¿Qué aspecto tiene la interfaz?


– Texto (CLI = Command Line Interface) (Incorpora un lenguaje sencillo para dar instrucciones
al SO, Cargar programas, trabajar con archivos, etc.).
– Gráfica (GUI = Graphical User Interface).
– Servicios de programación (API = Application Programming Interface).

2
Llamadas al sistema:
Llamada write() de UNIX. Escribe un bloque de datos en un fichero o en un dispositivo de E/S.

¿Qué ganamos interponiendo esta interfaz entre los programas y el hardware?


• Usabilidad: la interfaz es más cómoda que el hw.
• Seguridad: se ocultan vulnerabilidades del interior del hardware.
• Portabilidad: independencia del hardware.
• Interoperabilidad: podemos compartir información con otros sistemas que usen la misma
interfaz.
• Mantenibilidad: podemos hacer mejoras o adaptaciones dentro del SO sin obligar a hacer
cambios en los programas de usuario.
• Productividad: por todo lo anterior.

El SO como administrador de recursos


Proceso: programa en ejecución.
Recurso: algo físico o virtual que necesita un proceso para ejecutarse.
Los recursos son escasos  los procesos compiten por ellos.
El SO actúa como árbitro/mediador, que asigna recursos de forma justa y eficiente.
El SO debe determinar a quién se le entregan los recursos, qué cantidad, en qué momento y
por cuánto tiempo. (políticas de gestión de recursos).
• Criterios que deben cumplir las políticas del SO:
– optimizar el rendimiento del sistema.
– justicia en el reparto  evitar acaparamientos e inanición de los procesos perjudicados.
– garantizar la seguridad del sistema (confidencialidad, integridad, disponibilidad).
• Estos criterios entran en conflicto – Ej. no se puede dar el máximo rendimiento y al mismo
tiempo dar un reparto justo.

Seguridad: los tres elementos.


• CIA = Confidentiality + Integrity + Availability
• Confidencialidad: intimidad, privacidad, etc.
• Integridad: que la información no se corrompa.
• Disponibilidad: que el sistema continúe prestando servicio.

Algunos logros históricos de los SO.


• Interfaz uniforme con la E/S.
• Multiprogramación.
• Memoria paginada.
• Memoria virtual.
• Sistemas de archivos.
• Control del acceso concurrente.
• Protección y seguridad.

Interfaz uniforme con la E/S.


Ofrecer a los desarrolladores una API uniforme para acceder a cualquier dispositivo de E/S.
Para cada clase de dispositivo existe una implementación de esta API.
• ¿Qué conseguimos? (independencia del dispositivo)
– Abstraemos los detalles de implementación de cada clase de periférico.

3
– Ganamos en portabilidad (el mismo código sirve para dispositivos diferentes).
– Adaptación a futuras clases de periféricos.
– Podemos prohibir el acceso directo a la E/S (sólo trabajar con la API del SO)  más
seguridad.

Multiprogramación:
•También llamada multitarea (multitasking).
• Cuando un proceso se bloquea al esperar por la E/S, ejecutamos en la CPU instrucciones de
otro proceso.
• Los procesos entrelazan su ejecución: concurrencia.
• La CPU y la E/S trabajan a la misma vez  se terminan más trabajos en menos tiempo.
• Cuestiones que surgen en un sistema multiprogramado (y que no existen en un sistema sin
multiprogramación):
– Cuando el procesador queda libre, ¿a qué proceso elegimos?  planificación de CPU.
– Competencia por el consumo de la memoria.
– Protección de las zonas privadas de memoria.
– Conflictos ante el acceso simultáneo a los recursos.
– Riesgo de interbloqueo (deadlock).

Paginación y memoria virtual:


• Paginación: Podemos trocear un programa en pequeñas <<páginas>> que se pueden colocar
en zonas diferentes de la memoria.
• Memoria virtual: El programa no necesita estar cargado totalmente en memoria. El almacén
secundario se usa como extensión de la memoria principal.
• Todo se resuelve automáticamente, sin que el usuario ni el programador tengan que
intervenir.

Sistemas de archivos.
• Usuarios: trabajan con documentos, imágenes, programas, música, etc.
• Almacenamiento físico: trabajo con bloques de datos de tamaños fijo.
• Creamos un recurso virtual, llamado <<archivo>> que tiene nombre y contiene información.
También el concepto <<carpeta>> o <<directorio>> para organizar los archivos.
• Abstracción muy útil del almacenamiento físico.

Control del acceso concurrente.


¿Qué pasa si varios procesos intentan trabajar al mismo tiempo con un recurso que no se
puede compartir? – Ej. una impresora
• El SO debe conocer quién está usando el recurso y forzar la espera si está ocupado.
• No es trivial resolver este problema de forma segura y eficiente… (la solución, en el Tema 3).

Protección y seguridad. (solución más adelante)


• ¿Cómo evitamos que un proceso dañe la memoria ocupada por otro proceso, o por el SO?
• ¿Cómo impedimos que un proceso acceda directamente a la E/S, saltándose las políticas de
asignación de recursos?
• ¿Cómo garantizamos que los datos privados de un usuario no pueden ser leídos por
cualquier proceso?
• ¿Cómo nos aseguramos de que sólo las personas autorizadas pueden acceder al sistema?

4
Algunos tipos de sistemas.
• Procesamiento por lotes (batch processing).
• Tiempo compartido (time sharing).
• Tiempo real (real time).
• Sistemas multiusuario.
• Máquinas virtuales.

Sistemas de procesamiento por lotes (batch processing)


• Históricamente, fueron los primeros SO (principios de los 1950).
• Objetivo: automatizar la ejecución de trabajos y aumentar la utilización del procesador.
• Los trabajos se agrupaban en lotes que se iban ejecutando en secuencia.
• Los más primitivos eran secuenciales; la multiprogramación se incorporó a finales de los 50.
• Primer lenguaje para dictar tareas al SO  JCL (Job Control Language).

Sistemas de tiempo compartido (time sharing)


• Inventados en los 1950, comercializados en los 60.
• Avance sobre los sistemas por lotes, para conseguir interactividad.
• Cada proceso dispone de una pequeña rodaja de tiempo periódica. Los procesos se van
turnando en la CPU.
• Si la rodaja de tiempo es lo bastante pequeña (milisegundos), el usuario no percibe las
pausas periódicas de su sesión.

Sistemas de tiempo real (real time systems)


• Diseñados para cumplir tareas que deben completarse en un plazo prefijado (sistemas de
control industrial, sistemas multimedia…).
• Usan algoritmos de planificación de procesador especiales.
• S.T.R. crítico  para industria y sistemas empotrados en los que el cumplimiento de plazos
es crítico. Suelen prescindir de servicios que afectan a los tiempos (ej. Memoria virtual).

Sistemas multiusuario
• Un sistema multiusuario reconoce que hay varios perfiles de acceso, con privilegios distintos:
– Permisos de acceso a ficheros y aplicaciones.
– Cuotas de espacio o de tiempo de procesador.
– Prioridad en el acceso a los recursos.
• Ojo: multiusuario ≠ multitarea (puede haber sistemas multitarea que no son multiusuario).

Máquinas virtuales
• Emulación por software de una máquina física.
• Sobre la máquina virtual pueden ejecutarse programas implementados para la máquina
física emulada.
• Ventaja: no necesitamos el sistema original.
• Inconveniente: la emulación es más lenta.

Multiprocesadores
• Desde unos pocos hasta miles de procesadores
• Varios modelos de acceso a memoria
– UMA  memoria compartida
– NUMA  no compartida

5
• Varios modelos de ejecución de procesos:
– SMP  multiprocesamiento simétrico, una tarea se puede ejecutar en cualquier
procesador
– AMP  Multiprocesamiento asimétrico, hay especialización de tareas (ej. un procesador
ejecuta el SO y otro los procesos de usuario).

Sistemas distribuidos
• Un S.D. es un conjunto de computadores conectados en red y que se utiliza como si fuera un
único sistema con múltiples procesadores + una gran memoria compartida + un gran
almacenamiento secundario.
• No existe un «sistema distribuido universal», pero sí hay servicios con características de
sistema distribuido.
– Servicios en la nube (Dropbox, Amazon…).
– La WWW.

1.2 Estructura del computador y el SO.

• Los dispositivos se conectan al bus a través de controladores de E/S.


• La CPU se comunica con los controladores a través de instrucciones especiales o de
direcciones de memoria concretas.
• Cada controlador tiene un búfer local. La CPU envía y recoge datos del búfer.
• El controlador notifica a la CPU la finalización de una operación o la llegada de nuevos datos
mediante una interrupción.

Interrupciones
• Cuando llega una señal de interrupción a la CPU, ésta suspende lo que está haciendo y
ejecuta una rutina de servicio de interrupción (RSI).
• Antes de ejecutar la RSI, hay que guardar el estado de la CPU, para que pueda reanudar lo
que estaba haciendo después de completar la RSI.
• ¿Cómo sabe la CPU qué dispositivo ha interrumpido?

6
– Método primitivo: preguntando a todos los dispositivos  polling.
– Método avanzado: el dispositivo envía un número por el bus  interrupciones
vectorizadas.

Interrupciones vectorizadas
• Vector de interrupciones. Una zona de la memoria principal contiene las direcciones de todas
las RSI.
• El dispositivo que interrumpe envía un número por el bus de datos. El número sirve de índice
en el vector de interrupciones. La CPU ejecuta la RSI correspondiente.

El SO es un software reactivo
• El SO no se activa por sí solo. Se activa cuando ocurre un evento que tiene que atender 
comportamiento reactivo.
• Tipos de eventos: – Interrupciones del hardware – Llamadas al sistema – Excepciones.
• Cada tipo de evento activa una RSI diferente, indexada a través del vector de interrupciones.

Sincronización entre E/S y SO


• Cuando el SO solicita a un periférico una operación de E/S, ¿cómo espera a que la operación
finalice?
– De forma síncrona: el SO deja la CPU en espera hasta que llega la interrupción de la E/S.
– De forma asíncrona: el SO cede la CPU a otros procesos mientras la E/S va trabajando.
• Si trabajamos de forma asíncrona, podemos sacar más rendimiento al sistema.

Colas de espera por E/S


• Cuando se solicita E/S, el dispositivo puede estar ya ocupado.
• Hay que mantener en una cola de espera las peticiones pendientes.
• A medida que vayan finalizando las operaciones, el SO va alimentando la E/S con peticiones
encoladas.

Interrupciones software
• Las llamadas al sistema y las excepciones funcionan como interrupciones del software: se
gestionan igual que las interrupciones del hardware, pero las provoca la propia CPU.
• Para provocar una interrupción software, existe una instrucción de máquina específica:
– INT (Intel) – TRAP (Motorola) – SYSCALL (MIPS).

Jerarquía de memorias

7
¿Cómo gestionar la jerarquía de memorias?  memoria caché
• Aplicar el principio de caché: guardar en la memoria más rápida la información que se usa
con más frecuencia.
– Ejemplo: caché de disco.
– Ejemplo: caché de páginas web.
• La caché se acaba llenando. En ese caso, hay que descartar bloques de información que ya no
se necesitan  política de caché / política de reemplazo.
– Descartar el más antiguo (FIFO).
– Descartar el que hace más tiempo que se usó (LRU).
– Descartar el menos frecuentemente usado (LFU)
– Al azar.

Protección del hardware


• Para que el S.O. funcione adecuadamente, hay que impedir que los programas de usuario
puedan realizar libremente ciertas operaciones:
– Acceso a la memoria del S.O. y de otros programas.
– Acceso directo a los dispositivos de E/S.
– Utilizar la CPU todo el tiempo que quieran.
• Solución: modo dual de operación.

Modo dual de operación


• La CPU define un repertorio de instrucciones privilegiadas.
• Dos modos de operación del hardware:
– Modo privilegiado/supervisor/sistema. se pueden ejecutar todas las instrucciones.
– Modo no privilegiado/usuario: si se intenta ejecutar una instrucción privilegiada, la CPU
interrumpe la ejecución y genera una excepción.

¿Cuándo y cómo se cambia de modo?


• La CPU arranca en modo privilegiado.
• Cuando el S.O. cede el control al usuario, conmuta previamente a modo no privilegiado.
• Sólo se vuelve a modo privilegiado cuando el S.O. recupera el control, es decir, cuando
ocurre una interrupción, una llamada al sistema o una excepción.
• La instrucción especial para llamada al sistema (syscall, trap, etc.) conmuta automáticamente
a modo privilegiado.
• Por tanto, sirve para que el usuario cambie voluntariamente a modo privilegiado, pero
ejecutando código del S.O. que no está bajo su control.

Protección de memoria
• Idea: pareja de registros base y límite, que delimitan la zona de memoria en la que el usuario
está autorizado a trabajar.
• Cuando se está en modo usuario, se activa un circuito que verifica que la dirección de
memoria es legal.
• Los accesos indebidos no salen al bus. En vez de ello, se produce una excepción.

8
Protección de E/S
• Las operaciones de E/S deben ser privilegiadas.
• Dos modelos de acceso a la E/S:
– Con instrucciones especiales (in,out)  han de ser priviligiadas.
– A través de la memoria (memory mapped)  el acceso a las direcciones que usa la E/S
debe estar prohibido en modo usuario.

Protección contra abusos de CPU


• Objetivo: evitar que un proceso acapare indefinidamente el tiempo de CPU (p.ej. al entrar en
un bucle infinito).
• Solución: temporizador. Genera una interrupción tras un tiempo especificado (así el S.O.
recupera el control):
– Contiene un contador inicializado al valor que se desee.
– El contador se decrementa con cada pulso de reloj del sistema.
– Cuando el contador llega a cero, genera una interrupción.

1.3 Estructura del sistema operativo.


Programas del sistema

• Un SO es una plataforma de software que suele incluir un conjunto de utilidades básicas,


para:
– Darnos un entorno de trabajo (escritorio, shell…)
– Gestionar los recursos (formatear discos, configurar la red…)
– Trabajar con archivos (ls, cp, mkdir…)
– Editar documentos (vi, notepad, gedit…)
– Desarrollar programas (compilador, depurador…)
• Son lo que los usuarios perciben como «sistema operativo»
• Otros programas del sistema son servicios que se ejecutan en segundo plano (servicios,
subsistemas, demonios):
– Sistema de impresión
– Copias de seguridad
– Registro de actividad

9
El núcleo (kernel)
• Se suele llamar núcleo al componente del SO que reside en memoria de forma permanente y
atiende las llamadas al sistema y demás eventos.
• El resto de utilidades del SO (CLI, GUI, programas del sistema…) se apoyan en los servicios del
núcleo.
• En la parte teórica de la asignatura trataremos casi exclusivamente sobre el núcleo, no
abordaremos los otros componentes.

Implementación de las llamadas al sistema

• En el nivel del procesador:


– La llamada al sistema ocurre mediante una instrucción especial del procesador (syscall, int,
trap…).
– Esa instrucción cambia a modo privilegiado
• En el ámbito del programador:
– La llamada es una subrutina que escribimos en el código fuente. El compilador la acabará
sustituyendo por una invocación a la instrucción especial, con los argumentos que sean
necesarios.
• ¿Cómo se pasan los argumentos a la llamada?
– Mediante registros de CPU (lo más típico).
– Escribiéndolos en una tabla en memoria principal.
– Colocándolos en la pila.

Arranque típico de un SO
1. Cuando el equipo se enciende, la CPU inicia su ejecución en un punto fijo de la memoria.
2. Hay una ROM con una pequeña rutina de arranque.
3. La rutina localiza en qué dispositivo se encuentra el cargador del SO (boot loader) y lo carga
en memoria.
– Nota: La ROM del equipo tiene código para leer y escribir sobre los dispositivos de E/S
4. El cargador instala el núcleo y se continúa el proceso de carga de módulos, servicios, etc.
hasta que el SO queda totalmente operativo.

Arquitectura del SO
• ¿qué estructura interna tiene un SO?
• Algunas estructuras:
– Monolítico  todo en un mazacote de código.

10
– En capas  niveles de abstracción creciente.
• El SO se construye como una jerarquía de niveles, cada uno de los cuales aprovecha los
servicios del nivel inferior.
Sistema por capas puro (THE)
• Sistema experimental de los años 60
• Seis niveles:
– L5: aplicaciones de usuario
– L4: buffering
– L3: consola del operador
– L2: gestión de memoria paginada
– L1: planificación de procesos
– L0: hardware

– Micronúcleos  un pequeño SO sobre el que se añaden módulos.


• Dejar en el núcleo lo mínimo imprescindible
– Multitarea básica, gestión de interrupciones, comunicación entre procesos, E/S, etc.
• El resto de servicios se implementan como módulos en espacio de usuario
• Mecanismos en el micronúcleo, políticas fuera
• Los módulos se comunican con mensajes
• Primer micronúcleo: Mach (1980)
• Políticas  estrategias para administrar un recurso
– SJF, FIFO, tiempo compartido, LRU…
• Mecanismos  estructuras y objetos que sirven para implementar una política
– Colas de espera, bitmaps, despachador de procesos, temporizador, etc.
• Deseable que el código de los mecanismos y el de las políticas estén separados. Así se
pueden reutilizar los mecanismos para otras políticas.

11
• Ventajas:
– Se pueden construir servicios nuevos del SO sin tocar el núcleo.
– Se pueden implementar múltiples versiones para un mismo servicio (ej. varios sistemas de
ficheros).
– El SO es más fácil de portar a otras arquitecturas (sólo hay que tocar el micronúcleo).
– Más seguridad y fiabilidad (menos código en modo privilegiado).
• Inconvenientes:
– La comunicación entre módulos penaliza el rendimiento.

– Módulos cargables  módulos de código que se pueden incorporar al núcleo.


• Linux, Solaris…
• Módulos de código que se pueden incorporar al núcleo en tiempo de ejecución.
• Cada módulo tiene una interfaz conocida.
• Los módulos se hacen llamadas entre ellos.

12
Implementación del SO
• El SO presenta características especiales
– Pieza crítica: todas las aplicaciones dependen de él.
– Es mucho más complicado de depurar y de actualizar.
• Lenguaje de programación
– En el pasado, en lenguaje ensamblador (por eficiencia).
– Ahora en lenguajes de alto nivel, sobre todo C y C++
• Desarrollo modular
– Posibilidad de desarrollar módulos cargables por separado y dinámicamente.
• Disponibilidad del código fuente
– Sistema propietario  sólo tenemos los binarios ya compilados (Windows, Mac OS X,
OS/360…).
– Software libre  podemos tener la fuente y compilarlo en nuestro equipo (Linux,
FreeBSD…).

Tema 2. Procesos
¿Qué es un proceso?
• Un proceso es un programa en ejecución.
• Un proceso nuevo se crea a través de una llamada al sistema (Windows: CreateProcess; Unix:
fork, execve).
• Un proceso necesita recursos para poder ejecutarse: memoria RAM, dispositivos de E/S, la
CPU, etc.
• Casi siempre el proceso tendrá que competir con otros procesos para obtener tiempo de
CPU y áreas de memoria.
• A medida que un proceso se ejecuta, cambia de estado:
– Nuevo: recién creado por el S.O.
– En ejecución: está en la CPU ejecutando instrucciones.
– Bloqueado: esperando a que ocurra algún evento (ej. una operación de E/S).
– Preparado: esperando a que le asignen un procesador.
– Terminado: no ejecutará más instrucciones y el S.O. le retirará los recursos que consume.

13
Bloque de control de proceso (BCP)
• Cada proceso debe tener una estructura de datos que almacena su estado y otra información
de control:
– Valores de los registros de la CPU.
– Estado actual (preparado, bloqueado, etc.).
– Información para el planificador (prioridad, tiempo de espera…).
– Apuntadores a los recursos de memoria, E/S, archivos etc. que tiene concedidos o abiertos.
– Información de contabilidad (tiempo consumido….).

Planificación de la CPU (CPU scheduling)


• ¿Qué proceso utiliza la CPU en cada momento?
• Objetivos diferentes según el tipo de sistema:
– Sistemas por lotes à sacar rendimiento al procesador.
– Sistemas interactivos à garantizar tiempos de respuesta cortos.
– Tiempo real à garantizar plazos de ejecución.

Cola de planificación
• Conjunto de procesos en espera por la utilización de un determinado recurso
• Implementación: tabla, lista enlazada, árbol…
• El planificador inserta y extrae procesos de la cola de acuerdo con la política implementada.

Colas de procesos
• El SO organiza los BCP en colas de espera por el procesador o por los dispositivos de E/S.
(colas de planificación: cola de procesos, colas de dispositivos).

Niveles de planificación
• El planificador de corto plazo (PCP) o de bajo nivel es el que asigna y desasigna la CPU.
• En los sistemas por lotes, existe un planificador de largo plazo (PLP) o de alto nivel, que
suministra procesos a la cola de preparados.
• El PLP trata de conseguir una mezcla adecuada de trabajos intensivos en CPU y en E/S. Se
ejecuta con poca frecuencia.
• Planificador de medio plazo (PMP) (swapper). Envía al disco procesos bloqueados, para
liberar memoria principal a los otros procesos  intercambio (swapping).

14
Cambio de contexto (context switch)
• Es la operación que consiste en desalojar a un proceso de la CPU y reanudar otro.
• El módulo del SO encargado de esta acción se suele llamar despachador (dispatcher).
• Hay que guardar el estado del proceso que sale en su BCP, y recuperar los registros del
proceso que entra. Cada contexto se encuentra en cada BCP.
• El cambio de contexto es tiempo perdido, así que debe ser lo más rápido posible.
• El hardware a veces ofrece mecanismos para reducir el tiempo del cambio de contexto (ej.
en x86, instrucción PUSHA/POPA = guarda/recupera en la pila todos los registros; en ARM,
instrucciones LDM/STM).

API PARA TRABAJAR CON PROCESOS

¿Qué ofrece una API de procesos?


• Creación de nuevos procesos.
• Terminación de procesos.
• Comunicación entre procesos (IPC).

Creación de procesos
• Todo proceso se crea mediante una llamada al sistema ejecutada por otro proceso.
Ejemplos de llamadas al sistema: Windows  CreateProcess(); UNIX  fork(), exec().
• Al creador se le llama proceso padre y al nuevo, proceso hijo.
• Relación entre el padre y el hijo:
– ¿ejecutan el mismo código?
– ¿utilizan la misma área de memoria?
– ¿comparten archivos abiertos y otros recursos?
– cuando el padre termina, ¿el hijo muere con él?
• Cada proceso recibe un identificador único (PID en Unix y Windows).
• Los padres e hijos van formando un árbol de procesos.

15
Terminación de procesos
• Un proceso termina cuando invoca a una llamada al sistema específica, ej. exit()
• También si se genera una excepción y el S.O. decide abortarlo.
• En UNIX, cuando un proceso termina, con él mueren sus descendientes.
• Podría existir una llamada al sistema para abortar otro proceso, ej. kill()
• Esperar por la terminación de un proceso hijo: wait()

Comunicación entre procesos (IPC)


• ¿Cómo pueden intercambiar datos varios procesos? Dos modelos: Memoria compartida y
Paso de mensajes.
• Mecanismos clásicos (Unix, Windows):
– Ficheros normales (ineficiente).
– Zonas de memoria compartida.
– Tuberías (pipes).
– Sockets.
– Llamadas a procedimiento remoto (RPC).

HILOS (THREADS)

Un hilo, hebra o proceso ligero es una unidad básica de ejecución, con su propio:
contador de programa, registros de CPU y pila (stack).
• Los hilos dentro de una misma aplicación comparten:
código, datos y recursos del S.O. (ficheros, E/S, etc.).
• Hilos = procesos ligeros (lightweight processes).
• Un proceso pesado contiene uno o varios hilos que comparten la misma memoria y recursos.
– Proceso pesado = aplicación
– Hilos = actividades concurrentes dentro de la aplicación.

Beneficios de los hilos


• Ventajas de N hilos en un único proceso pesado, respecto a N procesos pesados:
– Comunicación más sencilla entre los procesos (memoria compartida).
– Más concurrencia con menos recursos (usan el mismo espacio de memoria para código y
datos).
– La conmutación entre hilos puede ser más eficiente (ej. al cambiar de hilo no hay que
limpiar cachés y tablas de páginas).

16
Hilos a nivel de usuario / de núcleo (kernel threads / user threads)
• Algunos sistemas manejan los hilos fuera del núcleo, dentro de la propia aplicación  hilos
de usuario (Java JVM clásica, POSIX threads, etc.).
• Hilos de núcleo  el propio núcleo es el que soporta los hilos (Actualmente, es el caso más
frecuente).
• En un sistema con hilos de usuario, el núcleo no «sabe» que un proceso tiene concurrencia
interna  si un hilo queda bloqueado, se bloquea a todo el proceso pesado.

Hilos implícitos / automáticos


• Objetivo: aliviar al programador del manejo de hilos.
• Compiladores, bibliotecas, lenguajes de programación… que tratan de crear y gestionar hilos
automáticamente a partir de indicaciones abstractas del programador.
• OpenMP, GCD (Apple), MTTD (Microsoft)…
• Lenguajes con marcas para identificar zonas concurrentes
– OpenMP, go (Google), GCD (Apple)…
– El entorno de tiempo de ejecución decide si se crea o no un hilo, dependiendo de los
recursos disponibles;
– O bien mantiene un «pool de hilos» de tamaño fijo y a medida que se quedan libres hilos
del pool se van ejecutando los bloques concurrentes.

2.2 Planificación de CPU


Planificación del procesador (processor scheduling)
• El sistema operativo decide qué proceso ocupa el procesador cuando éste queda libre.
• También en qué momento el proceso que está en ejecución debe abandonar el procesador.
• ¿Cuál es la «mejor» manera de decidir qué proceso entra en la CPU?
– ¿En orden de llegada, primero la tarea más corta, por prioridades…?

Debemos definir posibles criterios de valoración de las políticas.


• Podemos usar algunas magnitudes para medir el rendimiento de los algoritmos:
– Utilización de CPU: % de tiempo que la CPU está ocupada.
– Tiempo de retorno: tiempo transcurrido entre la llegada de un proceso y su finalización.
– Tiempo de espera: tiempo que un proceso permanece en la cola de preparados.
– Tiempo de respuesta: tiempo que un proceso bloqueado tarda en entrar en CPU, desde
que ocurre el evento por el que estaba esperando.
• Posibles objetivos de la planificación:
– Minimizar el tiempo medio de espera o de retorno.
– Maximizar la utilización de CPU.
– Mantener el tiempo de respuesta por debajo de un valor máximo, etc.
• Se pueden considerar las medias, valores extremos o varianzas de estas magnitudes.
• No existe una política de planificación óptima para todos los criterios. – Habrá que llegar a un
compromiso.

Modelo del sistema: ráfagas de CPU y E/S


• Podemos considerar que la vida activa de un proceso es una sucesión de:
– ráfagas de CPU  el proceso ejecuta instrucciones.
– ráfagas de E/S  el proceso utiliza o espera por la E/S.
• Según la utilización de los recursos, se observan:

17
– procesos intensivos en CPU (ej. cálculos numéricos).
– procesos intensivos en E/S (ej. interactivos).

Algoritmos expulsivos (preemptive)


• No expulsivos: el proceso que está en CPU la abandona solo cuando lo solicita
– riesgo de acaparamiento injusto de la CPU
– Windows 3.11, Apple Macintosh…
• Expulsivos: el planificador puede desalojar al proceso que está en CPU
– para implementar tiempo compartido y tiempo real, es necesaria una planificación
expulsiva: Unix, Windows NT, Mac OS X…

FCFS (first come, first served)


• La cola de preparados se gestiona como una FIFO.
• Simple de implementar.
• Muy sensible al orden de llegada de los procesos.
• Perjudica a los procesos intensivos en E/S (efecto convoy).

SJF (primero el más corto)


• SJF = Shortest Job First
• Entra en CPU el proceso con la ráfaga de CPU más breve.
• Versión expulsiva: Shortest Remaining Time First (SRTF)  El proceso en CPU es desalojado si
llega a la cola un proceso con duración más corta.
• Minimiza el tiempo de espera medio (óptimo).
• Riesgo de inanición de los procesos con ráfagas de larga duración.
• Pero… no se puede predecir la siguiente ráfaga  una implementación real debe calcular
una estimación.
– Posible estimación: media exponencial de las ráfagas anteriores
τ n+1 =α tn + (1−α) τ n
18
• El SJF no se utiliza en la práctica, ya que hay algoritmos con mejor equilibrio entre
rendimiento y tiempo de respuesta.

Planificación basada en prioridades


• Cada proceso tiene una prioridad asignada. Entra en CPU aquel con mayor prioridad.
– La política puede ser expulsiva o no.
– Prioridades definidas de forma interna (por el S.O.) o externa (por los usuarios).
– El SJF es un ejemplo (prioridad = duración estimada).
• Riesgo de inanición de los procesos con menos prioridad.
• Solución: envejecimiento (aging). Aumentar progresivamente la prioridad a los procesos en
espera.

Turno rotatorio (Round-Robin)


• Adecuado para implementar sistemas de tiempo compartido.
• Como el FCFS, pero cada proceso dispone de una «cantidad de tiempo» de duración Q para
estar en la CPU:
– si transcurre Q y el proceso continúa en CPU, el planificador lo desaloja y lo ingresa al final
de la cola de preparados
• La cola de preparados se gestiona con FIFO.
• Típicamente Q está entre 1 y 200 milisegundos.
• Si hay N procesos en cola, el tiempo de respuesta es como mucho: Qx(N-1)
• Si Q es muy grande, los procesos terminan sus ráfagas de CPU antes de que termine su
cuanto: se comporta como un FCFS.
• Si Q es muy pequeño, se tiende a un sistema en el que cada proceso dispone de un
procesador a 1/N de la velocidad del procesador real (procesador compartido).
• Si Q se vuelve muy pequeño, ocurren más cambios de contexto y baja el rendimiento (Q
debería ser mucho mayor que el tiempo que dura un cambio de contexto).

19
RR: modificaciones
• Q de duración variable, en función de la carga del sistema o de la prioridad del proceso que
entra en CPU.
• Ejemplo: en Linux (algoritmo CFS), cada proceso que entra en CPU recibe una Q proporcional
al tiempo que el proceso ha estado en espera y al número de procesos en el sistema.

Multicolas
• Varias colas de preparados, cada una gestionada con una política diferente. Ejemplo:
– Cola de procesos interactivos con RR.
– Cola de procesos por lotes con FCFS.
• Las colas se reparten la CPU según alguna política:
– Por prioridad absoluta.
– Un % de tiempo para cada cola, etc.
• Multicolas con realimentación.
– Posibilidad de que un proceso se mueva de una cola a otra, p.ej. si cambia su
comportamiento.
– Ej. UNIX clásico: un proceso que lleva mucho tiempo en espera se mueve a una cola de más
prioridad.

20
Planificación de multiprocesadores
• Procesamiento asimétrico. Un procesador se encarga de planificar el trabajo de los restantes
(técnica en desuso).
• Procesamiento simétrico. Cada procesador realiza su planificación.
– cola de preparados única en memoria compartida.
– una cola por procesador.
• Afinidad al procesador. Mantener al proceso siempre en un mismo procesador, para que
aproveche los datos que puedan estar en la caché de la CPU.
• Equilibrado de carga. Tratar de que no haya procesadores muy ocupados u ociosos.
– Migración comandada (push)  una tarea supervisora comprueba la carga y traslada
procesos.
– Migración solicitada (pull)  un procesador ocioso puede «robar» procesos a otro más
cargado.

Tema 3. Concurrencia
¿Qué es concurrencia?
• Definición de diccionario: coincidir en el espacio o en el tiempo dos o más personas o cosas.
• En Informática, se habla de concurrencia cuando hay una existencia simultánea de varios
procesos en ejecución.
• ¡Ojo! concurrencia existencia simultánea no implica ejecución simultánea.
• El paralelismo es un caso particular de la concurrencia: cuando hay ejecución simultánea de
instrucciones en varios procesadores.
• Computación distribuida: paralelismo en sistemas distribuidos o en red.
• Programación concurrente: Cuando aprendemos a programar, aprendemos algorítmica
secuencial (no permite expresar la concurrencia).
• ¿Cómo podemos expresar la concurrencia en nuestros programas?  Una API (pthreads),
Objetos concurrentes (java), Sentencias concurrentes (Ada, go).

21
• Sentencia concurrente: En este tema, expresaremos las actividades concurrentes con una
construcción llamada sentencia concurrente:

¿Para qué sirve la programación concurrente?


• Expresar mejor el mundo real (ej. las acciones concurrentes del desayuno)
• Especificar fragmentos de código que se pueden ejecutar en paralelo  aprovechar
múltiples procesadores.
• Expresar con más facilidad ciertos algoritmos (ej. monitor cíclico).

Comunicación y sincronización
• En muchos programas concurrentes, los procesos concurrentes son cooperativos y tienen
necesidad de comunicarse información.
– Si son hilos (ej. Java, C), se pueden comunicar mediante variables compartidas.
• Además, en ocasiones será necesario detener a un proceso hasta que se produzca un
determinado evento o se den ciertas condiciones  sincronización.
El problema de la concurrencia es que no sabe que método se va a ejecutar primero,
obteniendo un resultado inesperado (No determinismo).
Nota: no podemos suponer nada sobre la velocidad relativa de los procesos, ni el orden de
ejecución.

Solución: No se sabe porque puede ingresar primero


100 € y después sacar 50 €; o sacar 50 € pero el
sistema no te dejaría y después ingresar 100 €. Con lo
que tendrías dos soluciones: 50 € para el primer caso o
100 € para el segundo caso.

EL PROBLEMA DE LA SECCIÓN CRÍTICA

Sección crítica: modelo del sistema


• Surge cuando varios procesos intentan acceder continuamente a un recurso compartido.
• Segmento de código donde se accede a datos compartidos con otros procesos.
• Requisito: nunca debe haber más de un proceso dentro de la sección crítica (exclusión
mutua).

22
Posible solución
• Exclusión mutua.
• Progreso: si ningún proceso está en sección crítica y hay procesos que desean entrar en su
sección crítica, sólo estos últimos participarán en la decisión y ésta se tomará en un tiempo
finito.
• Espera limitada: hay un límite para el número de veces que otros procesos pueden
adelantarse a un proceso que quiere entrar en sección crítica.

Solución contundente: inhibir las interrupciones


• Antes de que un proceso entre en su sección crítica, se inhiben las interrupciones.
• Así es imposible que el proceso sea expulsado de la CPU mientras está accediendo al dato
compartido.
• Al salir de la SC, se rehabilitan las interrupciones.

Inhibir las interrupciones: inconvenientes


• Mientras un proceso está en SC, se suspende toda la concurrencia en el sistema  perjudica
a los procesos que no están intentando entrar en SC.
• NO sirve en multiprocesadores (no se puede enviar una señal simultánea a todos los
procesadores).
• NO garantiza espera limitada.

Soluciones software con espera activa (busy waiting)


• La sincronización se basa en que un proceso espera mediante la comprobación continua de
una variable.
• Ojo, la CPU se mantiene ocupada mientras el proceso espera (ineficiente).

Intento ingenuo: usar un indicador de disponibilidad

Primer intento serio: variable turno

23
Segundo intento: avisadores

Solución para 2 procesos: Algoritmo de Peterson

Solución para N procesos: Algoritmo de la panadería (Lamport)

24
Instrucciones hardware atómicas
• Inventadas en los años 60.
• Permiten evaluar y asignar un valor a una variable de forma atómica.
– test-and-set(B): Pone B a true y devuelve el antiguo valor de B.
– SWAP(A,B): Intercambia los valores de A y B.
• Si disponemos de estas instrucciones, se simplifica muchísimo el problema de la sección
crítica.

MUTEX (CERROJOS) Y VARIABLES CONDICIÓN

• La sección crítica no es el único problema de sincronización que nos podemos encontrar.


• La variedad de problemas de sincronización es infinita.
• Sería bueno disponer de herramientas y técnicas de programación que nos permitan resolver
cualquier problema de sincronización sin estar elaborando complejos algoritmos cada vez que
nos encontremos con un problema nuevo.

25
• Ejemplos:
– Esperar a que ocurra un evento o que finalice otro hilo.
– Problema del búfer finito (típico al gestionar una cola de acceso a un servicio).
– Problema de los lectores y escritores (típico en bases de datos).

Búfer finito (bounded buffer)


Procesos productores y consumidores que insertan/extraen elementos en una cola FIFO de
tamaño limitado.

Lectores y escritores
• Esquema útil para gestionar el acceso a una base de datos:
– Puede haber varios lectores accediendo a la BD de forma concurrente.
– Sólo puede haber un escritor trabajando.
– No puede haber lectores y escritores al mismo tiempo.
– … y si se puede, que no haya inanición.

Herramientas de sincronización
• Basadas en memoria compartida:
– Semáforos (Dijkstra, 1965).
– Regiones críticas condicionales (Hansen, 1972).
– Monitores (Hoare, 1972)  mutex, variables condición.
• No necesitan memoria compartida:

26
– Canales (Hoare, 1978).
– Buzones.
– Promesas y futuros (Friedman & Wise, 1976; Baker & Hewitt, 1977).

Mutex o cerrojo
• (mutex = “mutual exclusion”) Un objeto que sirve para adquirir en exclusiva el derecho de
acceso a un recurso.
• Dos posibles estados: libre y adquirido. Inicialmente está libre.
• Operaciones:
– lock()  Adquiere el mutex. Si el mutex ya estaba adquirido, el proceso se bloquea
hasta que lo consigue adquirir.
– unlock()  Libera el mutex. Si hay procesos en espera por el mutex, uno de ellos lo
adquiere y se desbloquea.
• Las operaciones garantizan ejecución atómica.

Variables condición
• Una variable condición sirve para gestionar una cola de espera por un recurso o una
condición lógica.
• La variable condicional está siempre asociada a un mutex.
• Operaciones:
– wait()  bloquea al proceso y lo mete en la cola de la v.c. Mientras el proceso está
bloqueado, se libera el mutex. Cuando el proceso se desbloquea, debe volver a
adquirir el mutex.
– signal()  desbloquea a un proceso de la cola; si no hay procesos en cola, no se hace
nada.
– broadcast()  desbloquea a todos los procesos de la cola.

27
¿Qué ocurre tras un «signal»?
• ¿Qué ocurre cuando un proceso P realiza una operación signal sobre una variable condición
C y existe un proceso Q bloqueado en C?
– Estilo Hoare  Q se reanuda inmediatamente (a P se le despoja del mutex).
– Estilo Mesa  Q se desbloquea, pero espera a que P libere el mutex.
• El «estilo Mesa» es el más utilizado en los lenguajes de programación actuales.
• ¿Qué ocurre si varios procesos están bloqueados en una variable condición C y algún proceso
ejecuta C. signal?, ¿cuál de los procesos se reanuda?
– FIFO  desbloqueamos al más antiguo.
– Por prioridades  conveniente en sistemas de tiempo real.
– Al azar  es lo que ocurre en implementaciones con espera activa.
– Desbloqueamos a todos y que ellos se peleen por el mutex (operación «broadcast»).

Mutex: implementación con espera activa.

28
Mutex: implementación sin espera activa.

Ojo: la implementación debe garantizar atomicidad


• Es crítico que las operaciones se ejecuten de forma atómica.
• Entorno uniprocesador: Inhibir interrupciones.
• Entorno multiprocesador: Instrucciones hardware especiales y aplicar un algoritmo de
sección crítica con espera activa.

PROBLEMAS CLÁSICOS DE SINCRONIZACIÓN

• Problema del búfer finito

29
• Problema de los lectores y escritores

• Primera variante: prioridad para los lectores.


– Si un escritor está esperando, se le pueden adelantar otros lectores.
– Ojo, riesgo de inanición para los escritores.
• Segunda variante: prioridad para los escritores.
– Si hay escritores esperando por la BD, los lectores que van llegando nuevos se deben
esperar hasta que todos los escritores finalicen.
– Ahora hay riesgo de inanición para los lectores.

• Problema de los filósofos

• Si los filósofos cogen los palillos sin control, se puede llegar a un estado de bloqueo mutuo
entre todos los filósofos  interbloqueo.
• Posibles soluciones:
– Algoritmo asimétrico filósofos pares/impares.
– Impedir a más de cuatro filósofos entrar a pedir los palillos.
– Coger los dos palillos de forma atómica (o coges los dos, o no coges ninguno).

30

También podría gustarte