250 likes | 413 Views
Multiprogramación Procesos. Cecilia Hernández 2007-1. Terminología. Multiprogramación Ejecutar multiples programas al mismo tiempo Requiere multiplexar la CPU Tranferencia de control entre programas en ejecución mediante Cambio de contexto Proceso : Programa en ejecución. gcc. firefox.
E N D
MultiprogramaciónProcesos Cecilia Hernández 2007-1
Terminología • Multiprogramación • Ejecutar multiples programas al mismo tiempo • Requiere multiplexar la CPU • Tranferencia de control entre programas en ejecución mediante • Cambio de contexto • Proceso : Programa en ejecución gcc firefox word firefox tiempo
Procesos Espacio de direccionamiento • Abstracción de SO de programa en ejecución • Asociado a un espacio de direccionamiento • Adelanto, múltiples hebras de control comparten mismo espacio de direccionamiento stack (mem dinámica) SP heap (mem dinámica) Datos estáticos (data segment) PC código (text segment)
Multiplexando CPU en el tiempo • SO mantiene estructuras de datos para identificar procesos • PCB (Process Control Block) • SO matiene un PCB por cada proceso que está ejecutando en el sistema (para cuando no están usando CPU) • SO ejecuta cambio de contexto para quitar y dar CPU a par de procesos • Salva estado de proceso que sale de CPU en PCB de proceso • Recupera estado de PCB de proceso que entra a CPU para luego ejecutarlo
PCB • Estructura de datos con muchos campos • Identificador de proceso (PID) • Estado de ejecución (Listo, en ejecución, bloqueado) • PC, SP, registros • Información de administración de memoria • Usuario al que pertenece • Prioridad en ejecución • Información para administración • En linux • Definida en task_struct (include/linux/sched.h) • Posee muchos más campos de los mencionados arriba
Estados de los procesos En ejecución Interrupción Sale de CPU Se despacha a CPU listo Espera E/S interrupción (completa E/S) Bloqueado
Colas de procesos • SO mantiene diversas colas para representar los procesos en el sistema • Cola de procesos listos: Procesos que están en condiciones de ejecutarse esperando por entrega de CPU • Cola de procesos bloqueados: Procesos que esperan por alguna condición para estar listos para ejecutarse • Cuando un proceso cambia de estado, su PCB se desenlaza de una cola para enlazarse a otra
Colas de Procesos firefox pcb emacs pcb gcc pcb Ptr head • Hay muchas colas de espera, una por cada tipo de espera (dispositivo E/S específico, red, etc) Ptr tail Encabezado cola listos Encabezado cola espera cat pcb firefox pcb Ptr head Ptr tail
Cambio de contexto • Proceso mediante el cual se cambia de un proceso en ejecución a otro • Proceso A entra en kernel • Producto de llamada a sistema, interrupción o excepción • El Planificador del SO se ejecuta • Es tiempo de cambio de contexto? • Si, sacar de cola de listos siguiente proceso a ejecutar. Proceso B • Rutina en assembly intercambia información de estado del HW • Salva el estado de proceso A en su PCB • Restaura estado de proceso B de su PCB • Salvar y recuperar estado, incluye CPU y adm de memoria virtual y resets de caches • Ejecuta proceso B • OS retorna a modo usuario
Cambio de contexto en linux • Para cambio relacionado con la memoria • Include/asm/mmu_context.h • Para cambio de recursos de CPU • include/asm/system.h • Aqui se define una macro llamada switch_to(prev,next,last) • Para mayor información de los detalles de esta macro revisar • Bovet Daniel P., Sesati Marco, “Understanding the Linux Kernel” (2nd Edition). O'Reilly Media, Inc. 2002
Procesos en Unix • Como crear aplicaciones usando procesos? • Usando Llamadas a sistema • Fork : crea un nuevo proceso • Exec : ejecuta un programa en proceso (varios formatos disponibles) • Kill : envia señales a procesos • Pueden ser de término o no • Wait : espera por proceso hasta que termina • Varios formatos
Creación de procesos en Unix • Usando llamada a sistema fork() • Básicamente, copia proceso padre • Proceso hijo obtiene un espacio de direccionamiento igual al del padre, pero es independiente • Proceso hijo hereda todos los archivos abiertos del padre • Fork se comporta diferente a cualquier llamado • Retorna dos veces • Retorna el pid del hijo al padre • Retorna 0 al hijo
Ejemplo fork #include <unistd.h> int value = 5; int main () { pid_t pid ; value = 7; pid = fork(); if (pid == 0) { // hijo value += 15; } else { // Padre wait (NULL); // espera a que hijo termine printf("PADRE: value = %d\n",value ); } } Qué valor es impreso en pantalla?
Fork versus exec • Fork() • Sólo permite crear nuevo proceso copiando al padre • Como hacer que el hijo ejecute algo diferente • Usando exec() • Ejemplo • Int exec( char *prog, char **argv) • Exec() • Detiene proceso actual • Carga programa ‘prog’ en espacio de direccionamiento • Inicializa nuevo contexto, args para ‘prog’ • Pone PCB proceso en cola de listos • NO CREA nuevo proceso, solo cambia lo que esta en espacio de direcciomiento
Variaciones de exec() int ret; ret = execl ("/bin/ls", "ls", "-1", (char *)0); char *env[] = { "HOME=/usr/home", "LOGNAME=home", (char *)0 }; ret = execle ("/bin/ls", "ls", "-l", (char *)0, env); ret = execlp ("ls", "ls", "-l", (char *)0) char *cmd[] = { "ls", "-l", (char *)0 }; ret = execv ("/bin/ls", cmd); char *cmd[] = { "ls", "-l", (char *)0 }; ret = execvp ("ls", cmd);
Variaciones wait() pid_t wait(int *status) pid_t waitpid(pid_t, int *status, int options)
Shell Unix int main(int argc, char **argv) { while (1) { char *cmd = get_next_command(); int child_pid = fork(); if (child_pid == 0) { exec(cmd); // vea variaciones de exec panic(“exec failed!”); } else { int st; waitpid(child_pid, &st, WIFEXITED(st)); } } }
Comunicación entre procesos • Usando señales SIGUSR1, SIGUSR2 • Ejemplo sigusuario.c • Usando Pipes • Permite la comunicación en un sentido entre dos procesos • Int pipe(int fds[2])
Pipe en un proceso Proceso de usuario read fd write fd kernel pipe -> Flujo de datos ->
Código que representa pipe en un proceso #include <unistd.h> main() { int pipefd[2], n; char buff[100]; if(pipe(pipefd) < 0) cout<<“error con pipe”<<endl; cout<<“read fd = %d, write fd = %d\n”, pipefd[0], pipefd[1]); if(write(pipefd[1], “hola yo mismo\n”, 14) != 14) cerr<<“error con write”<<endl; if ((n = read(pipefd[0], buff, sizeof(buff))) <=0 ) cerr<<“error con read”<<endl; write(1, buff, n); // 1 por salida estandar stdout }
Pipe en proceso padre/hijo después de fork Proceso hijo Proceso padre fork read fd read fd write fd write fd kernel pipe -> Flujo de datos ->
Comunicando padre con hijo en una dirección Proceso hijo Proceso padre fork read fd read fd write fd write fd kernel pipe -> Flujo de datos ->
Usando dup2 • int dup2(int oldfd, int newfd); • Permite duplicar oldfd creado con otro especificado en newfd, cerrando newfd primero si es necesario
Ejemplo usando dup2 int main(int argc, char **argv) { int pipefd[2]; int pid; pipe(pipefd); pid = fork(); if (pid == 0){ // este es el hijo dup2(pipefd[1], 1); close(pipefd[1]); cout<<" hola papa como estas ...\n"; } else { char msg[100]; dup2(pipefd[0], 0); close(pipefd[1]); cin.getline(msg,100); int st; waitpid(pid, &st, WIFEXITED(st)); cout<<" msg en padre "<<msg<<endl; cout<<" ahh!! me hijo se acuerda de mi\n"; } }