Programación Concurrente y Tiempo Real Laboratorio Sesión 2. Gestión de procesos Escuela Superior de Informática Universidad de Castilla-La Mancha Curso 2011/2012 Grado en Ing. Informática Primitivas básicas | Ejemplo paso a paso | Biblio Sesión 2. Gestión de procesos Identificando procesos ID proceso 1. Primitivas básicas 2. Un ejemplo paso a paso 3. Bibliografía #include <sys/types.h> #include <unistd.h> pid_t getpid (void); // ID del proceso pid_t getppid (void); // ID del proceso padre ID usuario #include <sys/types.h> #include <unistd.h> uid_t getuid (void); // ID del usuario uid_t geteuid (void); // ID del usuario efectivo Curso 2011/2012 Grado en Ing. Informática Curso 2011/2012 Primitivas básicas | Ejemplo paso a paso | Biblio Creación de procesos :: fork() + exec() proceso_A Trp 3 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Creación de procesos :: fork() + exec() fork() #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) execl() SIGCHLD wait() Curso 2011/2012 Limpieza tabla proc exit() zombie Trp 4 de 23 Curso 2011/2012 Trp 5 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Creación de procesos :: fork() + exec() Primitivas básicas | Ejemplo paso a paso | Biblio Espera y tratamiento de señales Primitivas básicas Primitivas básicas #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> 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[]); 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[]); Curso 2011/2012 Trp 6 de 23 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); Curso 2011/2012 Trp 7 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Espera y tratamiento de señales Primitivas básicas | Ejemplo paso a paso | Biblio Problemática archivo Primitivas básicas #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal (int signum, sighandler_t handler); sumador1 restador1 sumador2 restador2 ... ... sumadorn restadorn Condición de carrera Curso 2011/2012 Trp 8 de 23 Curso 2011/2012 Primitivas básicas | Ejemplo paso a paso | Biblio Problemática cont++ r1 = cont r1 = r1 + 1 cont = r1 cont-r2 = cont r2 = r2 - 1 cont = r2 Primitivas básicas | Ejemplo paso a paso | Biblio Modelo de gestión de procesos [cont = 7] De forma concurrente... p: p: c: c: p: c: r1 = r1 = r2 = r2 = cont cont cont r1 + 1 cont r2 + 1 = r1 = r2 [r1 = [r1 = [r2 = [r2 = [cont [cont 7] 8] 7] 8] = 8] = 8] manager.c manager recursos sumadores restadores fichero sumador.c restador.c [cont = 8] (cont != 7) Condición de carrera Curso 2011/2012 Trp 10 de 23 Curso 2011/2012 Primitivas básicas | Ejemplo paso a paso | Biblio Lanzando sumadores... Trp 11 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Lanzando restadores... manager.c // Se lanzan los sumadores... for (i = 0; i < P_SUMADORES; i++) switch (pid_hijo = fork()) { case 0: // Cada sumador recibe el nombre del archivo // y el número de incrementos a realizar execl("./exec/sumador", "sumador", ARCHIVO, pNumOp, NULL); break; } Curso 2011/2012 Trp 9 de 23 Trp 12 de 23 manager.c // Se lanzan los restadores... for (i = 0; i < P_RESTADORES; i++) switch (pid_hijo = fork()) { case 0: // Cada restador recibe el nombre del archivo // y el número de decrementos a realizar execl("./exec/restador", "restador", ARCHIVO, pNumOp, NULL); break; } Curso 2011/2012 Trp 13 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Pasando parámetros a un proceso Primitivas básicas | Ejemplo paso a paso | Biblio El proceso sumador execl sumador.c #include <unistd.h> #include #include #include #include int execl (const char *path, const char *arg, ...); <sys/types.h> <unistd.h> <stdlib.h> <stdio.h> Paso de parámetros void sumador (const char *pFileName, const char *pNumOP); // Conversión de NUM_OPERACIONES a char*... sprintf(pNumOp, "%d", NUM_OPERACIONES); int main (int argc, char *argv[]) { sumador(argv[1], argv[2]); execl("./exec/sumador", "sumador", ARCHIVO, pNumOp, NULL); } Curso 2011/2012 Trp 14 de 23 return 0; Curso 2011/2012 Primitivas básicas | Ejemplo paso a paso | Biblio El proceso sumador Trp 15 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Espera procesos hijo sumador.c manager.c void sumador (const char *pFileName, const char *pNumOP) { FILE *fp; int i, valor, operaciones; // 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); } printf("%d incrementando...\n", getpid()); operaciones = atoi(pNumOP); for (i = 0; i < operaciones; i++) fp = fopen(pFileName, "r"); fscanf(fp, "%d", &valor); // fclose(fp); valor++; // fp = fopen(pFileName, "w"); fprintf(fp, "%d", valor); // fclose(fp); } void esperar (int senhal) { int i; while (wait3(&i, WNOHANG, NULL) > 0); } { Lectura Actualización Escritura } Curso 2011/2012 Trp 16 de 23 Curso 2011/2012 Primitivas básicas | Ejemplo paso a paso | Biblio Gestión de interrupciones Trp 17 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Gestión de interrupciones manager.c manager.c // Manejo de Ctrol+C. if (signal(SIGINT, controlador) == SIG_ERR) { fprintf(stderr, "Terminación incorrecta.\n"); exit(1); } void controlador (int senhal) { printf("\nCtrl+c capturada.\n"); // Liberación de recursos... // Se muestra el contenido real del archivo... int valor; FILE *fp = fopen(ARCHIVO, "r"); fscanf(fp, "%d", &valor); fclose(fp); printf("Valor real: %d\n", valor); while(1) // Bucle infinito de espera. pause(); // A la espera de señales. // Salida del programa. exit(0); } Curso 2011/2012 Trp 18 de 23 Curso 2011/2012 Primitivas básicas | Ejemplo paso a paso | Biblio Modelo de Makefile Makefile := := := := obj/ exec/ include/ src/ manager: $(DIROBJ)manager.o $(CC) $(LDFLAGS) -o $(DIREXE)$@ $^ sumador: $(DIROBJ)sumador.o $(CC) $(LDFLAGS) -o $(DIREXE)$@ $^ CFLAGS := -I$(DIRHEA) -c -Wall LDFLAGS := -lrt CC := gcc restador: $(DIROBJ)restador.o $(CC) $(LDFLAGS) -o $(DIREXE)$@ $^ all : dirs manager sumador restador $(DIROBJ)%.o: $(DIRSRC)%.c $(CC) $(CFLAGS) $^ -o $@ dirs: mkdir -p $(DIROBJ) $(DIREXE) Curso 2011/2012 Primitivas básicas | Ejemplo paso a paso | Biblio Modelo de Makefile Makefile DIROBJ DIREXE DIRHEA DIRSRC Trp 19 de 23 clean : rm -rf *~ core $(DIROBJ) $(DIREXE) $(DIRHEA)*~ $(DIRSRC)*~ Trp 20 de 23 Curso 2011/2012 Trp 21 de 23 Primitivas básicas | Ejemplo paso a paso | Biblio Ejecución Bibliografía manager.c Valor inicial: 7 Valor esperado: 7 8967 incrementando... 8970 decrementando... 8968 decrementando... 8965 incrementando... 8966 incrementando... 8969 decrementando... ^C Ctrl+c capturada. Finalizando... Primitivas básicas | Ejemplo paso a paso | Biblio #define #define #define #define #define ARCHIVO "./test.txt" VALOR_INICIAL 7 P_SUMADORES 3 P_RESTADORES 3 NUM_OPERACIONES 3 ● ● Robbins, K.A., Robbins, S., Unix Programación Práctica, Sec. 2.3-2.7 Rochkind, M.J., Advanced Unix Programming, Sec. 5.3, 5.5, 5.7, 5.8, 5.9 Valor real: 3 OK! Curso 2011/2012 Trp 22 de 23 Curso 2011/2012 Trp 23 de 23