Procesos 1 / 31 Concepto de proceso ■ Para entender el concepto de hebra, necesitamos compreender el concepto de proceso ■ Un proceso es un programa en ejecución ■ Una instancia de un programa corriendo en un computador ■ Unidad de actividad caracterizada por la ejecución de una secuencia de instrucciones, un estado actual, y un conjunto asociado de recursos del sistema Fernando R. Rannou Diinf-USACH 2 / 31 Elementos tı́picos de un proceso ■ Identificador ■ Estado ■ Prioridad ■ Program Counter o PC ■ Contexto, es decir contenidos del conjunto de registros asociados al proceso ■ Espacio de direcciones con 1. Programa ejecutable 2. Datos globales 3. Stack del usuario 4. Stack del sistema ■ Información de status de I/O ■ Información de contabilidad Fernando R. Rannou Diinf-USACH 3 / 31 1 Bloque de control de proceso (PCB) ■ Estructura de datos que contiene los elementos de procesos ■ Creado y manejado por el SO ■ Contiene la informacin necesaria para interrumpir un proceso en ejecucin y luego reanudarlo (como si la interrupcin no hubiera ocurrido) Fernando R. Rannou Diinf-USACH 4 / 31 2 Modelo simple de estados de un proceso ■ Un proceso puede estar en uno de dos estados: 1. Corriendo, es decir ejecutándose en el procesador 2. No corriendo; en el sistema, pero fuera del procesador Fernando R. Rannou Diinf-USACH 5 / 31 3 Modelo de proceso de 5 estados ■ El estado no-corriendo se divide en dos: listo y bloqueado ■ Por conveniencia, se agregan dos estados más: Nuevo y Salir. Despachar Termino Entrar Nuevo No corriendo Corriendo Salir Time-out Evento ocurre Esperar evento Bloqueado Fernando R. Rannou Diinf-USACH 6 / 31 Modelo de 5 estados ■ Corriendo (running): el proceso est corriendo, es decir est en el procesador ■ Listo (ready): el proceso est listo para ejecutarse ■ Bloquado (blocked): no puede ejecutarse hasta que un evento dado ocurra. Ej: operacin de I/O termine ■ Nuevo (new): est recin creado, pero an no ha sido admitido en la cola de Ready. Ej. An no ha sido cargado en memoria ■ Fin (exit): un proceso que, por algn motivo, ya no sigue ejecutndose en el sistema Fernando R. Rannou Diinf-USACH 7 / 31 4 Ejemplo transición entre estados Proceso A Proceso B Proceso C Dispatcher 0 2 4 6 8 10 12 14 Fernando R. Rannou Diinf-USACH 16 18 8 / 31 Uso de múltiples colas de espera ■ El SO puede organizar los procesos en colas de espera, según sus estados ■ Ası́, existiı́a una cola de listos, otra de espera por I/O de disco, otra para I/O de interface de red, etc. Fernando R. Rannou Diinf-USACH 9 / 31 5 Procesos suspendidos ■ El procesador es mucho ms veloz que los dispositivos de I/O, y sera posible que todos los procesos en memoria estuvieran esperando por I/O ■ “Swapear” temporalmente algunos de estos procesos a disco y as liberar memoria. ■ Procesos que han sido swapeados a disco desde el estado de bloqueados, pasan al estado Suspendido (suspended) ■ Note que swapping es una operacin de I/O Fernando R. Rannou Diinf-USACH 10 / 31 Modelo de estados con un estado suspendido Despachar Entrar Nuevo Termino No corriendo Corriendo Salir Time-out Activar Evento ocurre Esperar evento Bloqueado Suspendido Suspender Fernando R. Rannou Diinf-USACH 11 / 31 6 Modelo de estados con dos estados suspendidos ■ ■ ■ Bloqueado: proceso en memoria principal y esperando por un evento Bloqueado/Suspendido: proceso en memoria secundaria y esperando por un evento Nuevo Suspender Admitir Admitir Despachar Termino Activar Listo/ Suspendido Corriendo No corriendo Salir Suspender Listo/Suspendido: proceso en memoria secundaria, pero listo para ejecucin en cuanto se cargue en memoria principal Time-out Evento ocurre Evento ocurre Esperar evento Suspender Bloqueado/ Suspendido Bloqueado Activar Fernando R. Rannou Diinf-USACH 12 / 31 La imagen de un proceso Se llama imagen de un proceso a la colección de: Identificador Proceso ■ Programa: Código ejecutable (texto) ■ Datos del usuario: Datos locales, globales, constantes, etc. ■ Stack del usuario para llamado a procedimientos, paso de parámetros, etc. ■ Stack del sistema ■ PCB Contexto del Proceso Control del Proceso Stack del sistema Stack del usuario Datos Programa Espacio de direcciones compartidas Fernando R. Rannou Diinf-USACH 13 / 31 7 Cambio de contexto (process switch) ■ Un cambio de contexto ocurre cada vez que el procesador comienza o reanuda la ejecución de un proceso distinto (al actual). ■ ¿Cuándo hacer un cambio de contexto? 1. Trap: interrupción asociada a un error de la ejecución de la instrucción actual. 2. Interrupción: evento externo a la ejecución del proceso 3. Interrupción del reloj por término de tiempo I/O 4. Fallo de memoria. La dirección de memoria no se encuentra actualmente en memoria principal. 5. Llamado al sistema (system call): por ejemplo instrucción de I/O ■ Un cambio de contexto o cambio de proceso no es lo mismo que un cambio del modo de ejecución del procesador. Fernando R. Rannou Diinf-USACH 14 / 31 Labores en un cambio de contexto ■ Guardar el contexo del proceso incluyendo el PC y otros registro. ■ Actualizar el PCB del proceso que actualmente est en ejecucin. ■ Mover el PCB de la cola de listo a la cola apropiada. ■ Seleccionar otro proceso para ejecucin. ■ Actualizar el PCB del proceso seleccionado ■ Actualizar las estructuras de administracin de memoria ■ Restaurar el estado del procesador al que tena cuando se estaba ejecutando el proceso seleccionado Fernando R. Rannou Diinf-USACH 15 / 31 8 Ejecución del sistema operativo 1. Ejecución en el contexto de un proceso usuario ■ Cada vez que se solicita un servivio al SO, simplemente se realiza un llamado a una rutina del SO, pero no hay cambio de contexto. ■ Hay cambio de modo usuario a modo kernel ■ Un número pequeño de tareas, como por ejemplo cambio de contexto, pueden ejecutarse fuera del contexto usuario 2. Basado en procesos ■ Implementa las tareas del SO como una coleccin de procesos del sistema ■ Útil en sistemas multiprocesadores y multicomputadores, pues permiten que los servicios prestados por los procesos puedan ser ejecutados exclusivamante en algunos procesadores y ası́ mejorar rendimiento. Fernando R. Rannou Diinf-USACH 16 / 31 Cambio del modo de ejecución ■ Existen dos modos principales para la ejecución de procesos: 1. Modo usuario : Es un modo no privilegiado, en el cual el proceso no puede ejecutar instrucciones reservadas al kernel 2. Modo kernel : En este modo, el proceso puede ejecutar cualquier tipo de instrucciones y tiene el control absoluto del sistema ■ En SO donde el kernel se ejecuta en el contexto de procesos usuarios (Unix, por ejemplo) es necesario realizar cambio en el modo de ejecución cada vez que un proceso invoca algún llamado al sistema ■ Recordar que el procesador chequea por interrupciones durante el ciclo fetch. ■ Si hay alguna interrupción pendiente, el procesador realiza lo siguiente: 1. Setea el PC con la dirección inicial del manejador de interrupciones 2. Cambia el modo del procesador de modo usuario a modo kernel, de manera que el manejador de interrupciones pueda ejecutar instrucciones privilegiadas. Fernando R. Rannou Diinf-USACH 17 / 31 9 Modelo de estados en Unix Fernando R. Rannou Diinf-USACH 18 / 31 Creación de procesos en Unix ■ fork() es el llamado al sistema para crear un nuevo proceso #include <sys/types.h> #include <unistd.h> pid_t fork(void); ■ fork() crea un proceso hijo, copia exacta del proceso padre. Lo único diferente es el identificador de proceso o pid ■ fork() retorna: 1. el pid del hijo en el padre 2. 0 en el hijo 3. -1 si hubo algún error ■ fork() es llamado una vez, pero retorna dos Fernando R. Rannou Diinf-USACH 19 / 31 10 Ejemplo 1 de fork() #include <sys/types.h> #include <unistd.h> main() { int pid; if ( (pid = fork()) == -1) { printf("No se pudo crear hijo\n"); exit(-1); } if (pid == 0) { // soy el hijo printf("Soy el hijo y mi pid = %d\n", getpid()); printf("Hijo: el pid de mi padre es = %d\n", getppid()); exit(0); } else { // soy el padre printf("Soy el padre y mi pid = %d\n", getpid()); printf("Padre: el pid de mi hijo es %d\n", pid); printf("Padre: el pid de mi padre es %d\n", getppid()); exit(0); } } Fernando R. Rannou Diinf-USACH 20 / 31 Ejemplo 2 de fork() Fernando R. Rannou Diinf-USACH 21 / 31 11 Identificadores ■ En sistemas Unix-like cada proceso tiene al menos seis identificadores asociados con el. ◆ pid t getpid(void): ID del proceso “llamador” (el que invoca) ◆ pid t getppid(void): ID del padre del proceso ◆ uid t getuid(void): ID del usuario real del proceso ◆ uid t geteuid(void): ID del usuario efectivo del proceso ◆ gid t getgid(void): ID del grupo real del proceso ◆ gid t getegid(void): ID del grupo efectivo del proceso ■ El usuario y grupo real identifican quién realmente somos y son seteados al momento de hacer login al sistema (archivo password /etc/passwd) ■ El usuario y grupo efectivo definen los permisos de acceso del proceso a los archivos. Fernando R. Rannou Diinf-USACH 22 / 31 El 1/2 ambiente de un proceso El medio ambiente de un proceso se refiere a todos aquellos elementos que permite que un proceso se ejecute; incluye ■ Cómo comienza la ejecución de un proceso; ■ Los recursos asociados y sus lı́mites; ■ El layout en memoria principal; ■ Los argumentos de linea de comando; ■ Las variables de medio ambiente. Fernando R. Rannou Diinf-USACH 23 / 31 12 La función main() ■ Un programa en C comienza su ejecución cuando la funciı́on main() es invocada. int main(int argc, char *argv[]); ◆ argc es el número de argumentos en lı́nea de comandos ◆ *argv[] es el vector de punteros los argumentos de lı́nea de comandos Ejemplo: $ sort -n 100 -o file.txt ◆ argc es 5 ◆ argv[] = {‘‘sort’’, ‘‘-n’’, ‘‘100’’, ‘‘-o’’, ‘‘file.txt’’} ■ En realidad, el kernel llama a una rutina start-up la cual finalmente invoca a main Fernando R. Rannou Diinf-USACH 24 / 31 Inicio, ejecución y término de un proceso ■ Cuando el proceso invoca exit(), el proceso realiza operaciones de “limpieza” antes de retornar al kernel. ■ Cuando el proceso invoca exit(), el proceso retorna inmediatamente al kernel. Fernando R. Rannou Diinf-USACH 25 / 31 13 La función atexit() ■ Esta función le permite al proceso registrar manejadores de salida, es decir funciones que se ejecutan cuando el proceso termina. #include <stdlib.h> int atexit(void (*func)(void)); ■ Cuando el proceso termina, se invocan las funciones registradas con atexit() en el orden inverso al que fueron registradas static void limpieza(void); int main(int argc, char *argv[]) { if (atexit(limpieza) != 0) err_sys("error registrar limpieza()"); printf("eso es todo, amigos\n"); return(0); } static void limpieza(void) { printf("limpiando...\n"); } Fernando R. Rannou Diinf-USACH 26 / 31 Variables de 1/2 ambiente ■ Un proceso puede acceder a sus variables de 1/2 ambiente mediante el puntero environ extern char **environ; ■ Cada variable consiste de un par nombre=valor y pueden ser leı́das por el proceso usando la función char *getenv(const char *name); ■ Estas “variables” no tiene valor para el kernel; el significado es dado por las aplicaciones environ "HOME=/home/batman" "PATH=/bin:/usr/bin" "SHELL=/bin/bash" "USER=batman" "PWD=/home/batman/lab1" NULL Fernando R. Rannou Diinf-USACH 27 / 31 14 Layout de un proceso Linux en memoria $ cat /proc/self/maps 001c2000-001c3000 r-xp 002b8000-002d1000 r-xp 002d1000-002d2000 r-xp 002d2000-002d3000 rwxp 00c87000-00dc4000 r-xp 00dc4000-00dc6000 r-xp 00dc6000-00dc7000 rwxp 00dc7000-00dca000 rwxp 08048000-0804d000 r-xp 0804d000-0804e000 rw-p 0987f000-098a0000 rw-p b7db6000-b7fb6000 r--p b7fb6000-b7fb7000 rw-p b7fcf000-b7fd0000 rw-p bfaf8000-bfb0d000 rw-p $ size /bin/cat text data 18431 1036 001c2000 00000000 00019000 0001a000 00000000 0013d000 0013f000 00dc7000 00000000 00004000 0987f000 00000000 b7fb6000 b7fcf000 bfaf8000 bss 0 dec 19467 00:00 08:01 08:01 08:01 08:01 08:01 08:01 00:00 08:01 08:01 00:00 08:01 00:00 00:00 00:00 0 66950 66950 66950 67366 67366 67366 0 7294713 7294713 0 7264522 0 0 0 [vdso] /lib/ld-2.5.so /lib/ld-2.5.so /lib/ld-2.5.so /lib/i686/nosegneg/libc-2.5.so /lib/i686/nosegneg/libc-2.5.so /lib/i686/nosegneg/libc-2.5.so /bin/cat /bin/cat /usr/lib/locale/locale-archive [stack] hex filename 4c0b /bin/cat Fernando R. Rannou Diinf-USACH 28 / 31 Familia exec() ■ Si fork() crea un clon de un proceso, ¿cómo serı́a posible crear procesos hijos totalmente distintos a un padre? ■ execve() ejecuta un nuevo programa en el proceso que realiza la invocación ■ execve() no crea un nuevo proceso, sino que sobre-escribe el programa actual con uno nuevo #include <unistd.h> int execve(const char *filename, char *const argv [], char *const envp[]); ■ filename es el camino absoluto del programa ejecutable ■ argv[] es un arreglo con los argumentos de lı́nea de comandos ■ envp[] es el medio ambiente de ejecución del proceso ■ execve() no retorna si hubo éxito Fernando R. Rannou Diinf-USACH 29 / 31 15 Familia exec() Las siguientes funciones son front-ends de execve(): #include <unistd.h> int int int int int execl(const char *path, const char *arg, ...); execlp(const char *file, const char *arg, ...); execle(const char *path, const char *arg , ..., char * const envp[]); execv(const char *path, char *const argv[]); execvp(const char *file, char *const argv[]); Para recordar: ■ ”l” : lista uno a uno los argumentos ■ ”v” : entrega un vector con los argumentos ■ ”p” : usa el PATH definido en el medio ambiente del proceso para encontrar el ejecutable ■ ”e” : asigna un environment, es decir medio ambiente Fernando R. Rannou Diinf-USACH 30 / 31 Ejemplo de execve() #include <sys/types.h> #include <unistd.h> main() { int pid; if ( (pid = fork()) == -1) { printf("No se pudo crear hijo\n"); exit(-1); } if (pid == 0) { // soy el hijo if (execlp("ls", "ls", "/home/rannou", 0) == -1) { printf("no se pudo hacer exec\n"); exit(-1); } printf("bye"); } // soy el padre wait(pid); printf("mi hijo finalizo\n"); exit(0); } Fernando R. Rannou Diinf-USACH 31 / 31 16