SISTEMAS OPERATIVOS TRABAJO
Enviado por Rodrigo Alarcon Mandujano • 21 de Octubre de 2015 • Trabajo • 3.045 Palabras (13 Páginas) • 116 Visitas
Página 1 de 13
TGT 2331-10
SISTEMAS OPERATIVOS
Contenido
Introducción
Soporte de interrupciones
Conceptos de sistemas operativos
Planificación en sistemas de tiempo real
Mecanismos de sincronización y comunicación
Planificación de tiempo real con recursos compartidos
Conceptos de Sistemas Operativos
CONTENIDO
El sistema operativo como interfaz para las aplicaciones
Modos de ejecución
Threads y procesos
Control de procesos. Cambio de contexto
Gestión de la memoria
Gestión de la entrada/salida
Gestión de tiempos y temporización
BIBIOGRAFIA
Q. Li: Real-Time concepts for embedded systems. CMP Books, 2003.
A. Lafuente: Sistemas Operativos II. Apuntes de la asignatura. Edición 2009-10. http://www.sc.ehu.es/acwlaroa/SO2.htm
M.J. Rochkind: Advanced Unix Programming (2nd Edition), Addison-Wesley, 2004.
C. Rodríguez, I. Alegria, J. Abascal, A. Lafuente: Descripción funcional de los sistemas operativos. Síntesis, 1994.
S. Sánchez Prieto: Sistemas Operativos. Universidad de Alcalá de Henares, Servicio Editorial, 2005.
A. Silberschatz, P. Galvin, G. Gagne: Conceptos de Sistemas Operativos (7a edición). Willey, 2006.
A.S. Tanenbaum: Modern Operating Systems (3rd edition). Prentice-Hall, 2008.
El sistema operativo como interfaz para las aplicaciones
Los dos papeles del sistema operativo:
Proporciona a las aplicaciones una interfaz (llamadas al sistema) para el acceso a los recursos.
Arbitra y gestiona eficientemente el uso de los recursos.
Qué es un recurso:
Procesadores
Memoria
Dispositivos (de E/S, relojes, comunicaciones…)
Ficheros
El sistema operativo como interfaz para las aplicaciones
El sistema operativo como interfaz para las aplicaciones
Las llamadas al sistema (system calls) proporcionan una interfaz homogénea que abstrae las características físicas de los recursos.
Por ejemplo, una aplicación de reproducción de sonido funciona de la misma forma para reproducir un archivo sobre un disco duro o sobre una memoria flash.
Las llamadas al sistema se utilizan como llamadas a funciones de biblioteca.
Su especificación debe estar bien definida (p. ej., el man de Linux/UNIX).
El sistema operativo como interfaz para las aplicaciones (cont)
También se denominan APIs.
Estándares para compatibilidad de aplicaciones (p. ej: POSIX)
Proporcionan un mecanismo único de entrada al sistema mediante cambio a modo protegido:
La llamada se implementa mediante un trap.
Modos de ejecución
Las instrucciones máquina pueden ser normales o reservadas.
Las instrucciones reservadas acceden a espacios (de memoria y de E/S) protegidos.
Dos modos de ejecución: normal y protegido.
Las instrucciones privilegiadas sólo pueden ejecutarse en modo protegido.
Un programa se ejecuta, en principio, en modo normal.
La instrucción de cambio de modo es privilegiada.
¿Cómo pasar a modo protegido para acceder a recursos necesarios (dispositivos de E/S, etc)?
Modos de ejecución
Cambio de modo
Mecanismo unificado para paso de modo normal a modo privilegiado: vector de interrupciones (VI).
Los servicios del sistema se implementan en espacio protegido mediante rutinas que se direccionan a través del VI.
Rutinas de servicio de interrupción.
Excepciones
Llamadas al sistema operativo.
Las rutinas se ejecutan bien asíncronamente (interrupciones), bien llamadas desde el programa (interrupciones programadas o traps).
Mediante un instrucción especial de LM: INT
El retorno de la rutina restaura el modo de ejecución anterior.
Threads y Procesos
Flujo de ejecución:
Secuencia de valores que adopta el registro Contador de Programa (PC) durante la ejecución de un programa.
Requiere una pila (normalmente en memoria) para representar las llamadas/retorno a subrutinas).
Contexto de ejecución:
Estado del sistema asociado a la ejecución del programa. Incluye o puede incluir:
PC, SP (puntero a pila), pila
Estado del procesador
Estado de la memoria
Estado de la E/S
Threads y Procesos
Ejemplo: un proceso con tres threads
Ejemplo:
creación de un proceso LINUX
#include
#include
#include
int main (int argc, const char * argv[]) {
int pid;
printf("%d: Soy el padre!\n", getpid());
pid= fork();
if (pid == 0)
printf("%d: Soy el hijo!\n", getpid());
else
printf("%d: Soy el padre de %d\n", getpid(), pid);
printf("%d: Agur!\n", getpid());
exit(0);
}
Ejemplo
#include
#include
#include
int main (int argc, const char * argv[]) {
int pid;
printf("%d: Soy el padre!\n", getpid());
pid= fork();
if (pid == 0)
printf("%d: Soy el hijo!\n", getpid());
else
printf("%d: Soy el padre de %d\n", getpid(), pid);
printf("%d: Agur!\n", getpid());
exit(0);
}
Ejemplo
Ejemplo:
contexto de un proceso LINUX
#include
#include
#include
char a;
int f_ejemplo() {
a= 'H';
printf("%d: Soy el hijo! (%c)\n", getpid(), a);
return 0;
}
int main (int argc, const char * argv[]) {
int pid;
a= 'P';
printf("%d: Soy el padre! (%c)\n", getpid(), a);
pid= fork();
if (pid == 0)
f_ejemplo();
else {
printf("%d: Soy el padre de %d (%c)\n", getpid(), pid, a);
}
printf("%d: Agur!\n", getpid());
exit(0);
}
Ejemplo:
threads en LINUX
#include
#include
#include
#include
#include
void* pila;
char memoria_pila[64*1024];
char a;
int f_ejemplo() {
a= 'H';
printf("%d: Soy el hijo! (%c)\n", getpid(), a);
return 0;
}
int main (int argc, const char * argv[]) {
int pid;
a= 'P';
printf("%d: Soy el padre! (%c)\n", getpid(), a);
pila= &memoria_pila[0];
pid= clone(&f_ejemplo, (char*) pila + 1024*64, SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VM, 0 );
printf("%d: Soy el padre de %d (%c)\n", getpid(), pid, a);
printf("%d: Agur!\n", getpid());
exit(0);
}
Threads y Procesos (cont)
Las entidades de ejecución son los procesos/threads.
En terminología de TR, tareas (indistintamente).
Un thread (hilo) es un flujo de ejecución con un contexto reducido
PC, SP (puntero a pila), pila
Estado del procesador
Un proceso es un flujo de ejecución con un contexto ampliado
Estado de la memoria
Estado de la E/S
Puede haber entidades de ejecución intermedias
Sistemas combinados: un proceso incluye un conjunto de threads
En este caso las entidades de ejecución/planificación son los threads
Threads y procesos
Threads y procesos
Threads y Procesos
Estados y grafo de transición
Nota: se toma aquí el proceso como entidad de ejecución, sin pérdida de generalidad.
Control de procesos
Representación
Bloque de Control de Procesos (PCB)
Identificador.
Estado del proceso.
Información para la planificación (prioridad, quantum).
Contadores de consumo de recursos (tiempo de CPU).
Puntero a la pila del proceso
En sistemas combinados: puntero a los threads del proceso (representados por TCBs).
Puntero a los recursos de memoria (tablas de páginas).
Puntero a los recursos de E/S (tabla de descriptores).
Control de procesos
Representación
Los PCBs se enlazan en colas
Una cola por estado
Incluso para el estado ejecutándose.
Proceso nulo: al menos un proceso preparado para ejecución.
Estado bloqueado: una cola por cada condición de bloqueo.
Control de procesos
El sistema operativo como un sistema de colas
Control de procesos
Planificación
La planificación de procesos (o threads) es la función del sistema operativo que decide qué proceso va entrar a ejecutándose y cuándo.
La realiza el scheduler.
Se elige un proceso de entre la cola de preparados de acuerdo a un criterio:
FCFS
Prioridades
Estáticas. Se asigna una prioridad al proceso cuando se crea y no cambia durante su ejecución.
Dinámicas. A partir de una prioridad inicial, se ajusta durante la ejecución de acuerdo a determinados criterios (p. ej. consumo de CPU del proceso).
Control de procesos
Planificación (cont)
Cuándo planificar:
Sólo cuando la CPU queda libre
porque el proceso ejecutándose termina o se bloquea: sistemas no expulsores
Además, los sistemas operativos expulsores, sacan al proceso que está ejecutándose
cuando ha consumido un quantum de tiempo:
Combinado con FCFS: planificación de turno circular o Round-Robin
cuando otro proceso llega a preparados.
Le da la oportunidad de ejecutarse inmediatamente. Como veremos, combinada con prioridades estáticas esta planificación expulsora es adecuada para tiempo real.
El cambio de contexto es el conjunto de operaciones necesarias para realizar una transición de un proceso (o thread) a otro:
Guardar el contexto del proceso que abandona la CPU.
Restaurar el contexto del proceso seleccionado por el scheduler.
Transferirle el control.
Además, actualizar la representación de los procesos en colas de PCBs.
Implica manipular las pilas de procesos
Se implementa en lenguaje máquina.
Gestión de la memoria
Se refiere a la memoria principal (RAM), donde un programa almacena su código, sus datos y su pila.
Gran diversidad de técnicas y políticas, dependiendo de si el programa se almacena:
Estática o dinámicamente.
Contiguo o en trozos.
Algunas técnicas (paginación, memoria virtual) requieren importante soporte hardware:
MMU, hoy en día on-chip.
Almacenamiento secundario (memoria virtual).
Las técnicas más elaboradas (memoria virtual) son incompatibles con el tiempo real.
Gestión de la memoria
Técnicas
Monitor residente
Particionado
Swapping
Paginación y segmentación
Memoria virtual
Otras: solapamientos y rutinas de enlace dinámico
Gestión de la memoria
Monitor residente
Para un único programa en memoria
Gestión de la memoria
Particionado
Particionado fijo (MFT)
Gestión de la memoria
Particionado
Particionado variable (MVT)
Gestión de la memoria
Particionado
En particionado fijo se pierde espacio dentro de las particiones (fragmentación interna).
¿Qué hacer si llega un programa nuevo y la partición adecuada a su tamaño está ocupada?
Encolarlo hasta que se libere.
Ejecutarlo en una partición mayor libre.
En particionado variable el espacio se pierde en los huecos entre programas (fragmentación externa).
Tiende a aumentar (cada vez más huecos más pequeños): degradación de la memoria.
Compactar para recuperar espacio.
Implica reubicación dinámica.
Gestión de la memoria
Particionado
Políticas de asignación de huecos
¿En qué hueco almacenar un nuevo programa?
¿En el más ajustado al tamaño del programa?
¿En en más grande?
¿En el primero que se encuentre?
Gestión de la memoria
Swapping
Un programa puede, durante su ejecución, abandonar la memoria.
Implica reubicación dinámica de programas.
Gestión de la memoria
Paginación y segmentación
Los programas se dividen en trozos
De igual tamaño (paginación)
De tamaño variable (segmentación)
Como consecuencia, un programa no aparece contiguo en memoria.
Dirección virtual vs dirección física.
Las direcciones donde se almacenan los trozos se guardan en tablas de páginas/segmentos.
Traducción dinámica de direcciones
Requiere importante soporte Hw:
Unidad de gestión de memoria (MMU)
Buffers de traducciones (TLB)
Permite compartir páginas/segmentos entre programas.
Gestión de la memoria
Paginación
La tabla de páginas puede ocupar mucho espacio.
Gestión de la memoria
Segmentación
Produce fragmentación externa.
Gestión de la memoria
Sistemas combinados
Varios niveles de indirección.
El último, siempre de paginación.
Gestión de la memoria
Memoria virtual
Se implementa sobre un sistema paginado.
Permite la ejecución de programas no enteros.
La referencia a una página no cargada en memoria provoca un trap de fallo de página y la búsqueda de la página en disco.
Aún más soporte Hw:
Bit de validez
Trap de fallo de página
Espacio en disco (swap)
Soporte para el reemplazo de páginas
Amplio soporte del sistema operativo:
Política de reemplazo de páginas
Políticas de asignación de espacio entre programas
Introduce impredecibilidad en los tiempos de respuesta.
Gestión de la memoria
Solapamientos y enlace dinámico
¿Qué hacer si un programa no cabe en la RAM y no tengo soporte de MV?
Se estructura el programa y se divide en trozos o solapamientos (overlays)
Cada solapamiento, una función
Se añade una rutina de enlace dinámico que gestiona la carga de las funciones en tiempo de ejecución.
Las llamadas a funciones son ahora llamadas a la rutina de enlace con la función y sus parámetros como argumentos.
Inicialmente se carga en memoria el programa principal y la rutina de enlace.
Modernamente los sistemas operativos añaden este mecanismo (con otros propósitos): Dynamic Link Libraries o Run-Time Libraries.
Gestión de la entrada/salida
Los dispositivos de entrada/salida son muy heterogéneos:
Velocidad
Representación de los datos
Protocolos
Operaciones
Unidad de transferencia (bloques, caracteres…)
Tipos de errores
Modo de tratar la E/S: Encuesta, Interrupciones, DMA.
Interfaz de los dispositivos unificada mediante Controladores
Entrada/salida
Interfaz
Los Controladores de los dispositivos (Kdisp) ofrecen una interfaz entre los dispositivos y el nivel de lenguaje máquina.
Elementos de la interfaz:
Espacio de direcciones de E/S, que puede ser
Memory-mapped
Independiente del de memoria
Operaciones de E/S mediante instrucciones máquina
Memory-mapped: LOAD/STORE
Espacios independientes: IN/OUT
Las direcciones de E/S se asocian a los dispositivos (Registros de E/S) y tienen papeles específicos:
Registros de estado
Registros de datos
Registros de control
Entrada/salida
Modos
Encuesta
Espera activa sobre Registro de Estado
Acceso a Registro de Datos
Interrupciones
El dispositivo cuenta con una línea de interrupción
Cuando se activa la interrupción, se ejecuta la Rutina de Servicio que gestiona la E/S:
Comprobación sobre Registro de Estado
Acceso a Registro de Datos
Acceso Directo a Memoria (DMA)
Los dispositivos de bloques no involucran a la CPU en el acceso a cada byte
Se programa la operación de DMA
Se ordena su inicio sobre un Registro de Control del KDMA
El fin de la operación se anuncia mediante una interrupción
La Rutina de Servicio a la Interrupción de DMA comprueba sobre un Registro de Estado.
Gestión de la entrada/salida
Manejadores de dispositivos (drivers)
Driver: código que monopoliza el acceso al dispositivo.
El resto del sistema operativo es independiente del dispositivo.
Un modelo de entrada/salida: cliente-servidor
Las rutinas de E/S son clientes del driver.
Gestión de la entrada/salida
Manejadores de dispositivos (drivers)
Interfaz entre las Rutinas de E/S y el driver:
Descriptor del Dispositivo, configurado por el driver:
Estado del dispositivo
Modo de operación
Tablas de conversión
Apuntador a la cola de peticiones
Evento asociado al driver
IORB (Input/Output Request Block) para especificar una petición al driver:
Identificador del proceso cliente
Parámetros de la petición
Evento para sincronización con el final de la operación
Diagnóstico de la operación (a rellenar por el driver)
Gestión de la entrada/salida
Ejemplo de estado de la E/S
Gestión de la entrada/salida
Buffering
Para desacoplar las velocidades de funcionamiento de los dispositivos y la CPU, el SO proporciona buffers del sistema para almacenamiento temporal de la E/S.
Varios esquemas.
Gestión de la entrada/salida
El sistema de ficheros
El desarrollo de las memorias tipo flash posibilita que incluso los dispositivos más pequeños proporcionen un sistema de ficheros.
Las abstracciones del modelo de E/S proporcionan independencia entre el sistema de ficheros y el dispositivo soporte.
Ejemplo: FAT16 sobre floppy/HD/flash
Gestión de la entrada/salida
El sistema de ficheros
Características del sistema de ficheros:
Permanencia
Organización estructurada
En árbol
Nombre de un fichero: relativo-absoluto
Algunos ficheros son directorios
Atributos de un fichero
Tiempos de creación, Acceso…
Derechos de acceso
Tamaño
etc
El contenido se organiza en registros lógicos
Acceso concurrente a ficheros
Punteros independientes
Gestión de tiempos y temporización
El tiempo es un recurso peculiar.
La gestión del tiempo es un componente básico en cualquier sistema empotrado o de tiempo real.
Vamos a estudiar:
Tipos de relojes
Rutinas de servicio de la interrupción del reloj
Gestión de temporizadores
Gestión de tiempos y temporización
Relojes
Reloj de tiempo real (RTC)
Siempre en funcionamiento. Requiere alimentación propia.
Reloj Hardware
Se inicializa con el RTC en la inicialización.
Produce las interrupciones de reloj.
Suele ser programable (PIT, p. ej., Intel 8253).
Puede tener otras funciones (p. ej., refresco de la DRAM).
Reloj del sistema
Es un reloj software implementado por la ISR del PIT.
Cuenta interrupciones y las expresa en unidades de tiempo.
El tiempo en Linux
Comando para consultar el reloj del sistema:
date
Ajuste del reloj:
adjtimex (sólo puede ejecutarla root)
Cronómetro de alta resolución:
gettimeofday()
Gestión de tiempos y temporización Rutina de servicio de la interrupción del reloj
Funciones:
Soporte del reloj software (contador de unidades de tiempo, p. ej., segundos)
Para el tiempo del sistema
Para implementar temporizadores
Gestión del tiempo compartido (expulsión por fin de quantum).
Contabilidad del uso de recursos temporales (p. ej., tiempo de CPU).
Genera eventos periódicos
Gestión de tiempos y temporización Rutina de servicio de la interrupción del reloj
Ejemplo
ISR_del_reloj ()
{
...
ticks_por_segundo−−;
intervalo_CPU++;
if (ticks_por_segundo== 0) {
actualiza_tiempo_del_sistema();
señalar_evento(EVENTO_SEGUNDO);
ticks_por_segundo= UN_SEGUNDO;
}
if (intervalo_CPU == quantum) {
incrementa_gasto_CPU_del_proceso(intervalo_CPU);
intervalo_CPU= 0;
goto cambio_de_contexto;
}
...
eoi();
reti();
cambio_de_contexto:
expulsar_proceso();
dispatcher (scheduler());
}
Gestión de tiempos y temporización Gestión de temporizadores
El sistema proporciona un servicio de temporización:
Un proceso se duerme durante n unidades de tiempo.
El sistema gestiona cuándo despertar a cada proceso dormido.
Hay que definir la resolución del temporizador:
A mayor resolución más carga para el sistema.
Modelo:
Los procesos ponen su petición de temporización (usando un IORB).
Un gestor de tiempos (manejador), activado cada unidad de tiempo por la ISR del reloj, despacha las peticiones a medida que se cumplen, despertando al proceso correspondiente.
Gestión de tiempos y temporización
Implementación
Gestión de tiempos y temporización
Implementación
Gestión de tiempos y temporización
Implementación
Gestor_tiempos ()
{
...
while (TRUE) {
esperar_evento(EVENTO_SEGUNDO);
while (primero(peticiones_tiempo).plazo == 0)
señalar_evento(primero(peticiones_tiempo).evento;
eliminar(primero(peticiones_tiempo));
}
primero(peticiones_tiempo).plazo−−;
}
}
Ejemplo:
uso de temporizadores en Unix
#include
#include
#include
void fnula() {return;}
unsigned esperar_tiempo (unsigned seg) {
unsigned s;
s= alarm(seg);
pause();
return(s);
}
int main (int argc, const char * argv[]) {
int i;
unsigned t;
signal(SIGALRM, fnula);
for (i=1; i<5; i++) {
printf("espera (%d segundos)\n", i);
t= esperar_tiempo(i);
printf("despertado (%d)\n", t);
}
}
...
Disponible sólo en Clubensayos.com