T5-multithreading SO-Grado 2013-2014-Q1.

Slides:



Advertisements
Presentaciones similares
el 1, el 4 y el 9 tres cuadrados perfectos autosuficientes
Advertisements

UNIVERSIDAD PRIVADA SAN PEDRO ESCUELA INGENIERIA CIVIL
Capitulo 7: Procesamiento batch y el Job Entry Subsystem (JES)
GESTION DE PROCESOS.
DATSI, FI, UPM José M. Peña Programación en C DATSI, FI, UPM José M. Peña Programación en C.
Tabla de Contenido Concurrencia.
Configuración de Control
Internet y tecnologías web
TEMA 1 Introducción a la Programación Concurrente
CLASE 4 EL ENSAMBLADOR.
CLASE 3 SOFTWARE DEL MICROPROCESADOR
I.T.E.S.R.C. Romina Tamez Andrea Martínez Ma. De Lourdes Solís
Base de Datos Distribuidas Bases de Datos II Universidad Argentina J. F. Kennedy - Año 2008 Maletin Yahoo => briefcase.yahoo.com Usuario => bd2_jfk Pssw.
PROGRAMACIÓN PARALELA Tema 5: Análisis de algoritmos paralelos
INSTTUTO TECNOLOGICO DE APIZACO
Herramientas para anfitrión y presentador Servei de Formació Permanent i Innovació Educativa.
Modelo de procesos de dos estados
INFORMATICA I Arreglos 1 CLASE 17.
Informática II Prof. Dr. Gustavo Patiño MJ
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Informática II 1 Diego Fernando Serna RestrepoSemestre 2011/2.
Comunicación y sincronización entre procesos
SISTEMAS OPERATIVOS UNIDAD 1..
UTFSM - Sistemas Operativos
Índice Sesión I Bloque I (09:30 a 10:30 Horas) Configuración Inicial
JULIO BERNA. Los procesos de usuario emiten peticiones de entrada/salida al sistema operativo. Las peticiones se procesan de forma estructurada en las.
Tema 3. Optimización de Código
¿Qué es un PUNTERO?: Un puntero es un objeto que apunta a otro objeto. Es decir, una variable cuyo valor es la dirección de memoria de otra variable. No.
7a.1 Silberschatz, Galvin y Gagne ©2003 Sistemas Operativos 6ª edición Capítulo 7: Sincronización de procesos parte a.
Programación I Teoría VI: Recursividad
ConceptoDefiniciónCaracterísticas (palabra clave) Ejemplo/Aplicación Sistema operativo Un sistema operativo es un software, es decir, forma parte de la.
Clases y objetos La unidad fundamental de programación OO son las clases. Conjunto de métodos y semántica Qué se va a hacer POO Clase: que define la implementación.
Tema 6: Clases Antonio J. Sierra.
 2003 Prentice Hall, Inc. All rights reserved. 1 Capítulo 6: Clases y Abstracción de Datos Índice del capítulo 6.1 Introducción 6.2 Estructuras 6.3 Clases.
Programación de código reubicable
HILOS Y COMUNICACIÓN ENTRE PROCESOS
PONNHI PONNHI Una Nueva Arquitectura Microkernel Pthreads en Espacio de Usuario José Manuel Rodríguez García Juan A. Rico Gallego Jesús M. Álvarez Llorente.
Semana 5 Subprogramas..
Concurrencia: Exclusión Mútua y Sincronización
Conceptos generales: Concurrencia: Existencia simultánea de varios procesos en ejecución. IMPORTANTE: EXISTENCIA SIMULTÁNEA NO IMPLICA EJECUCIÓN SIMULTÁNEA.
Comunicación y sincronización entre procesos Realizado por Kepa Bengoetxea Kortazar
Ing Florencia Ferrigno Tecnicas Digitales 3
Unidad III Administración de procesos
Hilos - Lightweight process - Procesos ligeros
Profesor: Rodrigo Sanhueza Figueroa
IET110 Sistemas Operativos P04: Exclusión Mutua Prof. Jonathan MakucSlide: 1.
Hebras Cecilia Hernández. Qué es un proceso? Consiste Espacio de direccionamiento Código a ejecutar Datos estáticos y dinámicos Pila o stack CPU: PC,
 El acceso concurrente a datos compartidos puede dar pie a inconsistencia de datos  Mantener la consistencia de los datos requiere mecanismos para asegurar.
Introducción a los Sistemas Operativos
Gestión de procesos Sistemas Operativos Edwin Morales
Sincronización de Procesos
Tema 9.6: Sincronización de Procesos
TEMA 10. SISTEMAS OPERATIVOS DISTRIBUIDOS
1 Descripción y control de procesos Capítulo 3. 2 Requerimientos de un SO relacionados con procesos Ejecutar concurrentemente múltiples procesos para.
Teoría de Sistemas Operativos Sincronización Procesos Departamento de Electrónica 2º Semestre, 2003 Gabriel Astudillo Muñoz
Materia: Técnicas Digitales 3
Administrador de procesos
Introducción a los SOs.
Teoría de Sistemas Operativos Departamento de Electrónica 2º Semestre, 2002 Gabriel Astudillo Muñoz
Estructura de los Sistemas Operativos
Sistemas de Archivos Sistemas Operativos.  Se debe proporcionar un almacenamiento secundario que respalda a la memoria principal  El Sistema de archivos.
FLOR ALBA ACEVEDO COD JENNIFFER TATIANA TORRES COD
Unidad 2 – Gestión de Procesos
INTERRUPCIONES – ABRAZO MORTAL
Elementos y tipos de sistemas operativos
También es conocido como proceso ligero. Es una entidad básica de utilización de CPU y esta formado por un contador de programa, algunos registros y una.
MEMORIA DINÁMICA.
Desarrollador Profesional de Juegos Programación III Unidad II Hilos de ejecución Threads.
Estructura del sistema operativo
1 Tema 6: Concurrencia de Procesos Sistemas Operativos.
Transcripción de la presentación:

T5-multithreading SO-Grado 2013-2014-Q1

Indice Proceso vs. Flujos Librerías de flujos Comunicación mediante memoria compartida Condición de carrera Sección Crítica Acceso en exclusión mutua Problemas Abrazos mortales

Procesos vs. Flujos Hasta ahora….. Una única secuencia de ejecución: Sólo 1 Program Counter y una pila Concurrencia entre procesos, pero dentro de un proceso la ejecución era secuencial (una única secuencia de instrucciones) No es posible ejecutar concurrentemente diferentes funciones dentro del mismo proceso Aunque puedan haber partes del código independientes entre si

Ejemplo: aplicación cliente-servidor { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … } DATOS GLOBALES Servidor { While(){ Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); } Cliente 2 { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … } Cliente N { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … } Monoproceso: sólo un cliente cada vez Se desaprovecha las ventajas de la concurrencia y del paralelismo Multiproceso: un proceso para cada cliente simultáneo que se quiera atender Ejecución concurrente y/o paralela Pero… Se desaprovechan recursos Replicación innecesaria de estructuras de datos que almacenan los mismos valores, replicación del espacio lógico de memoria, mecanismos para intercambiar información,…

CASO : aplicación cliente-servidor { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … } DATOS GLOBALES Servidor { While(){ INICIO_proceso Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_proceso } Cliente 2 { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … } DATOS GLOBALES Servidor { While(){ INICIO_proceso Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_proceso } DATOS GLOBALES Servidor { While(){ INICIO_proceso Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_proceso } DATOS GLOBALES Servidor { While(){ INICIO_proceso Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_proceso } DATOS GLOBALES Servidor { While(){ INICIO_proceso Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_proceso } Cliente N { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … }

CASO : aplicación servidor Alternativa: procesos multiflujo Permitir diferentes secuencias de ejecución simultáneas asociadas al mismo proceso ¿Qué necesitamos para describir una secuencia de ejecución? Pila Program counter Valores de los registros El resto de características del proceso puede ser única (resto del espacio lógico, información sobre los dispositivos, gestión signals, etc)

Procesos vs. Flujos Los recursos se siguen asignando en su mayoría a los procesos: Espacio de direcciones Dispositivos Pero el SO planifica a nivel de Flujo (cada flujo necesita 1 CPU) Los flujos de un proceso comparten todos los recursos asignados al proceso y todas las características Y cada flujo tiene asociado: Siguiente instrucción a ejecutar (valor del PC) Zona de memoria para la pila Estado de los registros Un identificador Proceso tradicional: un sólo flujo de ejecución

CASO : aplicación cliente-servidor { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … } DATOS GLOBALES Servidor { While(){ INICIO_FLUJO Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_FLUJO } Cliente 2 { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … } INICIO_FLUJO Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_FLUJO INICIO_FLUJO Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_FLUJO INICIO_FLUJO Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_FLUJO INICIO_FLUJO Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_FLUJO INICIO_FLUJO Esperar_peticion(); Preparar_respuesta(); Enviar_respuesta(); FIN_FLUJO Cliente N { .. Enviar_peticion(); Esperar_respuesta(); Procesar_respuesta(); … }

Internamente: Procesos vs. Flujos 1 proceso con N flujos  1 PCB N secuencias del código del proceso que se pueden ejecutar de forma concurrente En el PCB hay espacio para guardar los contextos de los N flujos Descripción de memoria 1 región de código 1 región de datos 1 región de heap + N pilas (1 por flujo)

Procesos vs. Flujos

Internamente: Procesos vs. Flujos Compartición de memoria Entre procesos Por defecto la memoria es privada para un proceso y nadie la puede acceder (hay llamadas a sistema que permiten pedir zonas de memoria compartida entre procesos) Entre flujos Todos los threads pueden acceder a todo el espacio lógico de la tarea a la que pertenecen Cosas a tener en cuenta en la programación con threads Cada thread tiene su pila propia donde el compilador reserva espacio para sus variables locales, parámetros, y control de su ejecución Todas las pilas también son visibles por todos los flujos

Utilización de procesos multiflujos Explotar paralelismo y concurrencia Mejorar la modularidad de las aplicaciones Aplicaciones intensivas en E/S Flujos dedicados sólo a acceder a dispositivos Aplicaciones servidores

Ventajas de usar flujos Ventajas de usar varios flujos en lugar de varios procesos Coste en tiempo de gestión: creación, destrucción y cambio de contexto Aprovechamiento de recursos Simplicidad del mecanismo de comunicación: memoria compartida

Gestión a nivel de usuario: Librerías de flujos Los kernels ofrecen threads, pero su interfaz no es compatible (en general) como en el caso de los procesos, por eso se definió una interfaz implementada a nivel librería usuario. POSIX threads. POSIX threads (Portable Operating System Interface, definido por IEEE) Interfaz de gestión de flujos a nivel de usuario Creación y destrucción Sincronización Configuración de la planificación El API de POSIX es muy potente, dependiendo del kernel la librería implementa toda la funcionalidad o solo parte de ella

Servicios de gestión de flujos Creación Procesofork() Flujos  pthread_create(out Pth_id,in NULL, in function_name, in Pparam) Identificación Procesos: getpid() Flujos : pthread_self() Finalización Procesos: exit(exit_code) Flujos:pthread_exit(in Pthexit_code) Sincronización fin de flujo Procesos: waitpid(pid,ending_status, FLAGS) Flujos:pthread_join(in thread_id, out PPexit_code) Consultad las páginas de man para ver los tipos de datos exactos

Creación de flujos pthread_create Crea un nuevo flujo que ejecuta la rutina start_routine pasándole como parámetro arg #include <pthread.h> int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); th: contendrá el identificador del thread attr: características del thread (si NULL se le asignan las características por defecto) start_routine: @ de la rutina que ejecutará el nuevo flujo. Esa rutina puede recibir un sólo argumenteo de tipo void * (nombre de la función) arg: parámetro de la rutina Devuelve un código de error o 0 si ok

Identificación del flujo pthread_self Obtiene el identificador del flujo que la ejecuta #include <pthread.h> int pthread_self(void); Devuelve el identificador del thread

Destrucción de flujos pthread_exit #include <pthread.h> La ejecuta el flujo que acaba la ejecución Se pasa como parámetro el valor de retorno del thread #include <pthread.h> int pthread_exit(void *status); status: valor de retorno del thread Devuelve un código de error o 0 si ok

Sincronización con el fin de un flujo pthread_join Bloquea al flujo que la ejecuta hasta que el flujo indicado acabe y recoge el valor que ha pasado al pthread_exit Provoca la liberación de la estructura de datos asociada al flujo #include <pthread.h> int pthread_join(pthread_t th, void **status); th: identificador del thread al que se espera status: contendrá el parámetro que el flujo th le pasó al pthread_exit. Si NULL se ignora el parámetro del pthread_exit. Devuelve código de error o 0 si ok

Comunicación mediante memoria compartida Los flujos de un proceso pueden intercambiar información a través de la memoria que comparten Accediendo más de uno a las mismas variables Problema que puede aparecer: condición de carrera (race condition) Cuando el resultado de la ejecución depende del orden el que se alternen las instrucciones de los flujos (o procesos)

Ejemplo: race condition int primero = 1 /* variable compartida */ /* flujo 1 */ If (primero) { primero --; tarea_1(); } else { tarea_2(); } /* flujo 2 */ If (primero) { primero --; tarea_1(); } else { tarea_2(); } TAREA1 TAREA2 FLUJO 1 FLUJO 2 FLUJO 1 Y FLUJO 2 -- RESULTADO INCORRECTO La idea del programador era utilizar este booleano para que se ejecutara primero la tarea1 y luego la 2 (pero cada una solo 1 vez) Lo que no tuvo en cuenta es que estas operaciones no son atómicas!!!

Que tenemos en ensamblador??? haz_tarea: pushl %ebp movl %esp, %ebp subl $8, %esp movl primero, %eax testl %eax, %eax je .L2 subl $1, %eax movl %eax, primero call tarea1 jmp .L5 .L2: call tarea2 .L5: leave ret Esto es el if no es 1 instrucción Esto es la resta  no es 1 instrucción Esto es el else Que pasa si hay un cambio de contexto después del movl del if al thread 2???

¿Qué pasaría?…eax valdrá 1 al volver!! FLUJO 1 FLUJO 2 haz_tarea: pushl %ebp movl %esp, %ebp subl $8, %esp movl primero, %eax testl %eax, %eax je .L2 subl $1, %eax movl %eax, primero call tarea1 jmp .L5 .L2: call tarea2 .L5: leave ret haz_tarea: pushl %ebp movl %esp, %ebp subl $8, %esp movl primero, %eax testl %eax, %eax je .L2 subl $1, %eax movl %eax, primero call tarea1 jmp .L5 .L2: call tarea2 .L5: leave ret Cambio! Cambio!

Región crítica Región crítica Líneas de código que contienen condiciones de carrera que pueden provocar resultados erróneos Líneas de código que acceden a variables compartidas cuyo valor cambia durante la ejecución Solución Garantizar el acceso en exclusión mutua a estas regiones de código ¿Evitar cambios de contexto?

Exclusión mútua Acceso en exclusión mutua: Se garantiza que el acceso a la región crítica es secuencial Mientras un flujo está ejecutando código de esa región ningún otro flujo lo hará (aunque haya cambios de contexto) El programador debe: Identificar regiones críticas de su código Marcar inicio y fin de la región usando las herramientas del sistema El sistema operativo ofrece llamadas a sistema para marcar inicio y fin de región crítica: Inicio: si ningún otro flujo ha pedido acceso a la región crítica se deja que continúe accediendo ,sino se hace que el flujo espere hasta que se libere el acceso a la región crítica Fin: se libera acceso a la región crítica y si algún flujo estaba esperando el permiso para acceder se le permite acceder

Interfaz pthreads Exc. mutua A considerar: Cada región crítica se identifica con una variable (global) de tipo pthread_mutex_t, por lo tanto, necesitamos 1 variable de este tipo por región. Antes de utilizarla, hay que inicializarla, por lo tanto, antes de crear los threads es lo ideal Función Descripción pthread_mutex_init Inicializa una variable de tipo pthread_mutex_t pthread_mutex_lock Bloquea el acceso a una región crítica pthread_mutex_unlock Libera el acceso a una región crítica

Ejemplo: Mutex int primero = 1 /* variables compartida */ pthread_mutex_t rc1; // Nueva, también compartida pthread_mutex_init(& rc1,NULL); // INICIALIZAMOS LA VARIABLE, SOLO 1 VEZ ….. pthread_mutex_lock(& rc1); // BLOQUEO if (primero) { primero --; pthread_mutex_unlock (& rc1); //DESBLOQUEO tarea_1(); } else { pthread_mutex_unlock(& rc1); //DESBLOQUEO tarea_2(); }

Exclusión mútua: consideraciones Cosas que el programador debe tener en cuenta Las regiones críticas deben ser lo más pequeñas posibles para maximizar la concurrencia El acceso en exclusión mutua viene determinado por el identificador (variable) que protege el punto de entrada No hace falta que tengan las mismas líneas de código Si varias variables compartidas independientes puede ser conveniente protegerlas mediante variables diferentes