8x1 - Escuela Superior de Informática - Universidad de Castilla

Anuncio
Programación Concurrente y
Tiempo Real
Tema 1. Conceptos Básicos
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Curso 2011/2012
Grado en Ing. Informática
Proceso | Prog. Concurrente | Prog. TR
Tema 1. Conceptos Básicos
El concepto de proceso
1. El concepto de proceso
1.1. Gestión básica de procesos [Silber 3.1]
1.2. Primitivas POSIX [Robb 2.5-2.7] [Rochk 5.1-5.7]
1.3. Procesos e hilos [Silber 4.1, 4.3.1]
2. Fundamentos de prog. concurrente
pila
instr_1
instr_2
instr_3
…
instr_i
3. Fundamentos de prog. en TR
…
memoria
carga del ejecutable
en memoria
datos
instr_n
texto
programa
Curso 2011/2012
Grado en Ing. Informática
Curso 2011/2012
Proceso | Prog. Concurrente | Prog. TR
Estados de un proceso
proceso
Trp 3 de 41
Proceso | Prog. Concurrente | Prog. TR
Identificadores
ID proceso
admitido
nuevo
terminado
interrupción
pid_t getpid (void); // ID del proceso
pid_t getppid (void); // ID del proceso padre
salida
preparado
#include <sys/types.h>
#include <unistd.h>
en ejecución
ID usuario
terminación E/S
en espera
#include <sys/types.h>
#include <unistd.h>
espera E/S
uid_t getuid (void); // ID del usuario
uid_t geteuid (void); // ID del usuario efectivo
Curso 2011/2012
Trp 4 de 41
Curso 2011/2012
Trp 5 de 41
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: fork()
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: fork()
fork()
proceso_A
#include <sys/types.h>
#include <unistd.h>
fork()
pid_t fork (void); // 0 al hijo; ID del hijo al padre
proceso_A
(cont.)
proceso_B
(hijo)
Ejemplo fork
int *valor = malloc(sizeof(int));
*valor = 0;
fork();
*valor = 13;
printf("%ld: %d\n", (long)getpid(), *valor); // ¿?
hereda_de
Curso 2011/2012
Trp 6 de 41
Curso 2011/2012
Trp 7 de 41
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: fork()
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: fork() + exec()
proceso_A
Cadena de procesos
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
1
int main (void) {
int i = 1, n = 4;
pid_t childpid;
2
fork()
proceso_A
(cont.)
proceso_B
(hijo)
3
for (i = 1; i < n; i++)
// ?
execl()
SIGCHLD
return 0;
4
}
Curso 2011/2012
wait()
Trp 8 de 41
Curso 2011/2012
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: fork() + exec()
exit()
zombie
Limpieza
tabla proc
Trp 9 de 41
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: fork() + exec()
Ejemplo. Padre crea n hijos
Primitivas básicas
#include <unistd.h>
Padre
int execl (const char *path, const char *arg, ...);
int execlp (const char *file, const char *arg, ...);
int execle (const char *path, const char *arg, ...,
char *const envp[]);
// padre.c
int execv (const char *path, char *const argv[]);
int execvp (const char *file, char *const argv[]);
int execve (const char *path, char *const argv[],
char *const envp[]);
for (i = 1; i <= n; i++)
switch(childpid = fork()) {
case 0: // Código del hijo.
execl("./exec/hijo", "hijo", argv[1], NULL);
break; // Para evitar entrar en el for.
}
// ¡Faltaría la espera del padre a los hijos!
Curso 2011/2012
Trp 10 de 41
pid_t childpid;
int n = atoi(argv[1]), i;
Curso 2011/2012
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: fork() + exec()
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: wait()
Hijo
Primitivas básicas
// hijo.c
#include <sys/types.h>
#include <sys/wait.h>
int main (int argc, char *argv[]) {
hijo(argv[1]);
return 0;
}
pid_t wait (int *status);
pid_t waitpid (pid_t pid, int *status, int options);
// BSD style
pid_t wait3 (int *status, int options,
struct rusage *rusage);
pid_t wait4 (pid_t pid, int *status, int options,
struct rusage *rusage);
void hijo (const char *num_hermanos) {
printf("¡Soy %ld y tengo %d hermanos!\n",
(long)getpid(), atoi(num_hermanos) - 1);
}
Curso 2011/2012
Trp 11 de 41
Trp 12 de 41
Curso 2011/2012
Trp 13 de 41
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: signal()
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: wait()
Primitivas básicas
Padre
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
// Se espera la terminación de los procesos...
if (signal(SIGCHLD, esperar) == SIG_ERR) {
fprintf(stderr, "No se esperó a un proceso.\n");
exit(1);
}
typedef void (*sighandler_t)(int);
sighandler_t signal (int signum,
sighandler_t handler);
// Manejo de Ctrol+C.
if (signal(SIGINT, controlador) == SIG_ERR) {
fprintf(stderr, "Terminación incorrecta.\n");
exit(1);
}
int kill (pid_t pid, int sig);
int pause (void);
while(1)
// Bucle infinito de espera.
pause(); // A la espera de señales.
Curso 2011/2012
Trp 14 de 41
Curso 2011/2012
Trp 15 de 41
Proceso | Prog. Concurrente | Prog. TR
Creación de procesos :: wait()
Proceso | Prog. Concurrente | Prog. TR
Procesos e hilos
Padre
void esperar (int senhal) {
int i;
while (wait3(&i, WNOHANG, NULL) > 0);
}
código
datos
registros
archivos
código
pila
registros
pila
void controlador (int senhal) {
printf("\nCtrl+c capturada.\n");
printf("Finalizando...\n\n");
// Liberar recursos...
printf("OK!\n");
// Salida del programa.
exit(0);
datos
registros
pila
archivos
registros
pila
hebra
}
Curso 2011/2012
Trp 16 de 41
Curso 2011/2012
Proceso | Prog. Concurrente | Prog. TR
Pthreads
Proceso | Prog. Concurrente | Prog. TR
Pthreads
Especificación POSIX, no implementación
Pthread
int main (int argc, char *argv[]) {
pthread_t tid;
pthread_attr_t attr;
Pthread
#include <pthread.h>
if (argc != 2) {
fprintf(stderr, "Uso: ./pthread <entero>\n");
return -1;
}
int pthread_create (pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
int pthread_join
Trp 17 de 41
pthread_attr_init(&attr); // Att predeterminados.
// Crear el nuevo hilo.
pthread_create(&tid, &attr, mi_hilo, argv[1]);
pthread_join(tid, NULL); // Esperar finalización.
(pthread_t thread, void **retval);
printf("Suma total: %d.\n", suma);
return 0;
}
Curso 2011/2012
Trp 18 de 41
Curso 2011/2012
Trp 19 de 41
Proceso | Prog. Concurrente | Prog. TR
Pthreads
Tema 1. Conceptos Básicos
Pthread
1. El concepto de proceso
void *mi_hilo (void *valor) {
int i, ls;
ls = atoi(valor);
i = 0, suma = 0;
2. Fundamentos de prog. concurrente
2.1.
2.2.
2.3.
2.4.
while (i <= ls)
suma += (i++);
pthread_exit(0);
}
Problema del productor/consumidor [Silber 6.1]
La sección crítica [Silber 6.2-6.4]
Mecanismos básicos de sincron. [Silber 6.5, 6.7]
Interbloqueos y tratamiento del deadlock [Silber 7]
3. Fundamentos de prog. en TR
Compilación
$ gcc -lpthread pthread.c -o pthread
$ ./pthread 7
Curso 2011/2012
Trp 20 de 41
Curso 2011/2012
Grado en Ing. Informática
Proceso | Prog. Concurrente | Prog. TR
Buffer limitado
Proceso | Prog. Concurrente | Prog. TR
Productor/consumidor
cont++
while (1) {
// Produce en nextP.
r1 = cont
while (cont == N);
r1 = r1 + 1
// No hacer nada.
buffer[in] = nextP;
cont = r1
in = (in + 1) % N;
cont++;
}
while (1) {
while (cont == 0);
// No hacer nada.
nextC = buffer[out];
out = (out + 1) % N;
cont--;
// Consume nextC.
}
while (1) {
// Produce en nextP.
while ((in + 1) % N == out);
// No hacer nada.
buffer[in] = nextP;
in = (in + 1) % N;
}
while (1) {
while (in == out);
// No hacer nada.
nextC = buffer[out];
out = (out + 1) % N;
// Consume nextC.
}
Curso 2011/2012
Trp 22 de 41
do {
SECCIÓN_ENTRADA
r2 = cont
r2 = r2 - 1
cont = r2
p:
p:
c:
c:
p:
c:
Curso 2011/2012
r1 =
r1 =
r2 =
r2 =
cont
cont
cont
r1 + 1
cont
r2 - 1
= r1
= r2
Trp 23 de 41
Proceso | Prog. Concurrente | Prog. TR
Sección crítica
cont--
Proceso | Prog. Concurrente | Prog. TR
Sección crítica :: Sol 1 (2 proc)
1. Exclusión mutua
2. Progreso
3. Espera limitada
do {
while (turn != i);
SECCIÓN_CRÍTICA
1. Exclusión mutua
2. Progreso
3. Espera limitada
SECCIÓN_CRÍTICA
SECCIÓN_SALIDA
turn = j;
SECCIÓN_RESTANTE
SECCIÓN_RESTANTE
while(1);
while(1);
Curso 2011/2012
Trp 24 de 41
Curso 2011/2012
Trp 25 de 41
Proceso | Prog. Concurrente | Prog. TR
Sección crítica :: Sol 2 (2 proc)
do {
flag[i] = true;
while (flag[j]);
Proceso | Prog. Concurrente | Prog. TR
Sección crítica :: Peterson (2 proc)
1. Exclusión mutua
2. Progreso
3. Espera limitada
do {
flag[i] = true;
turn = j;
while (flag[j] && turn == j);
SECCIÓN_CRÍTICA
SECCIÓN_CRÍTICA
flag[i] = false;
flag[i] = false;
SECCIÓN_RESTANTE
SECCIÓN_RESTANTE
1. Exclusión mutua
2. Progreso
3. Espera limitada
while(1);
while(1);
Curso 2011/2012
Trp 26 de 41
Curso 2011/2012
Proceso | Prog. Concurrente | Prog. TR
Sección crítica :: Lamport (n proc)
Trp 27 de 41
Proceso | Prog. Concurrente | Prog. TR
Sección crítica :: Hardware
do {
do {
eleccion[i] = true;
num[i] = max(num[0], ..., num[n]) + 1;
elección[i] = false;
for (j = 0; j < n; j++)
while (elección[j]);
while (num[j] != 0 && (num[j], j) < (num[i], i));
adquirir_cerrojo
SECCIÓN_CRÍTICA
Operaciones
atómicas
liberar_cerrojo
SECCIÓN_CRÍTICA
num[i] = 0;
while(1);
Curso 2011/2012
SEC_REST
1. Exclusión mutua
2. Progreso
3. Espera limitada
Trp 28 de 41
SECCIÓN_RESTANTE
while(1);
Curso 2011/2012
Trp 29 de 41
Proceso | Prog. Concurrente | Prog. TR
Sección crítica :: Swap
Proceso | Prog. Concurrente | Prog. TR
Sincronización :: Semáforos
do {
do {
key = true;
while (key == true)
swap(&lock, &key);
wait (sem)
SECCIÓN_CRÍTICA
void swap (boolean *a,
boolean *b)
{
// a := b
// b := a
}
lock = false;
SECCIÓN_RESTANTE
Operaciones
atómicas
SECCIÓN_CRÍTICA
swap
while(1);
signal (sem)
SECCIÓN_RESTANTE
while(1);
Curso 2011/2012
Trp 30 de 41
Curso 2011/2012
Trp 31 de 41
Proceso | Prog. Concurrente | Prog. TR
Sincronización :: Semáforos
Proceso | Prog. Concurrente | Prog. TR
Sincronización :: Paso de mensajes
Memoria
compartida
while (1) {
// Produce en nextP.
wait (empty);
wait (mutex);
// Guarda nextP en buffer.
signal (mutex);
signal (full);
}
while (1) {
wait (full);
wait (mutex);
// Rellenar nextC.
signal (mutex);
signal (empty);
// Consume nextC.
}
Message
Message
Message
Proceso1
Proceso2
Message
Message
Message
Curso 2011/2012
Trp 32 de 41
Curso 2011/2012
Trp 33 de 41
Proceso | Prog. Concurrente | Prog. TR
Sincronización :: Paso de mensajes
Proceso 1
Proceso 2
while (1) {
// W_previo_1
send ('*', P2)
// W_restante_1
}
while (1) {
// W_previo_2
receive (&msg, P1)
// W_restante_2
}
Proceso | Prog. Concurrente | Prog. TR
Sincronización :: Monitores
Datos
compartidos
Condiciones
x
y
Operaciones
Código
inicialización
Sincronización (P2 no avanza
hasta que no recibe de P1)
Operaciones con exclusión mutua
dentro del monitor
Curso 2011/2012
Trp 34 de 41
Curso 2011/2012
Trp 35 de 41
Proceso | Prog. Concurrente | Prog. TR
Interbloqueos
Proceso | Prog. Concurrente | Prog. TR
Grafos de asignación de recursos
R1
R1
Condiciones de
Coffman
●
●
●
●
Exclusión mutua
Retener y esperar
No apropiación
Espera circular
R2
P1
Esperando R2...
P={P1, P2, P3}
R={R1, R2, R3, R4}
E={P1-->R1,
R1-->P2,
...}
P1
P2
P3
P2
Esperando R1...
R2
Curso 2011/2012
R3
Trp 36 de 41
Curso 2011/2012
R4
Trp 37 de 41
Proceso | Prog. Concurrente | Prog. TR
Grafos de asignación de recursos
R1
Proceso | Prog. Concurrente | Prog. TR
Tratamiento del deadlock
Métodos tratamiento deadlock
R3
P2
R1
P1
P2
P3
P1
Impedir o evitar
Detectar y recuperar
P3
Ignorar
1
Prevención
Evasión
Evitar las 4
condiciones
Coffman
Política
asignación
recursos
Info sobre
el estado de
recursos
2
Algoritmo
detección
P4
R2
R4
R2
Curso 2011/2012
Trp 38 de 41
3
Algoritmo
recuperación
Curso 2011/2012
Trp 39 de 41
Proceso | Prog. Concurrente | Prog. TR
Evasión del deadlock
Tema 1. Conceptos Básicos
1. El concepto de proceso
Algoritmo
del banquero
2. Fundamentos de prog. concurrente
Peticiones de recursos
3. Fundamentos de prog. en TR
Algoritmo de
seguridad
¿Estado
seguro?
No
Deshacer
3.1. Definición de STR [Burns 1]
3.2. Características [Burns 1]
3.3. Introducción al diseño de STR [Burns 2]
Sí
Asignar recursos
Curso 2011/2012
Trp 40 de 41
Curso 2011/2012
Grado en Ing. Informática
Descargar