La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Llamadas al Sistema EXIT y WAIT

Presentaciones similares


Presentación del tema: "Llamadas al Sistema EXIT y WAIT"— Transcripción de la presentación:

1 Llamadas al Sistema EXIT y WAIT
Alumnos : Cristo Manuel Alonso Santana Inti Sologuren Marrero

2 Llamada al sistema exit
La finalidad de exit() es poner fin a la existencia de un proceso. Está contenida en el fichero fuente: kernel/exit.c Implementada por la función sys_exit(), la llamada exit pasa por ser la llamada al sistema número 1. Sys_exit() a su vez invoca a do_exit pasándole el código de retorno

3 Perspectiva del Sistema Operativo
Cuando se invoca a la llamada exit(), el sistema operativo reacciona reclamando todos los recursos que tiene asociado el proceso que ha de finalizar. Ficheros asociados Sistema de Ficheros Memoria utilizada Señales pendientes

4 Sintaxis void exit () El valor devuelto al proceso padre será cero en caso de finalización normal y distinto a cero si finaliza debido a un error. Cuando el proceso hijo termina le envía al padre una señal SIGCHLD y espera hasta que el valor estado sea aceptado por el padre, permaneciendo en estado zombie.

5 Implementación sys_exit()
int sys_exit (int error_code) { do_exit((error_code&0xff)<<8); } La función sólo convierte el código de retorno al formato esperado por do_exit, que es quien realmente lleva a cabo la implementación.

6 Descriptores de Proceso
Task struct Estructura principal del proceso. Files_struct Referencia a los archivos asociados del proceso. Fs_struct Asocia el sistema de ficheros con el proceso Signal_struct Acciones asociadas a las señales del proceso. Mm_struct Memoria asociada Namespace Información acerca del sistema de ficheros

7 Task_struct Struct task_struct { }
volatile long state; /*Estado del proceso (TASK ZOMBIE)*/ unsigned long flags; /*Información adicional(PF_EXITING)*/ int exit_code; /*Exit code para el padre*/ int pid; /*Sistema de ficheros*/ struct fs_struct* fs; /*Sistema de ficheros*/ struct mm_struct* mm /*Memoria asociada*/ struct files_struct* files; /*Ficheros asociados*/ struct signal_struct* sig; /*Acciones asociadas*/ struct namespace* namespace; /*Información del Sist. Ficheros.*/ }

8 Struct fs_struct Struct fs_struct {
int count; /* Nº de procesos que referencian este handle*/ struct inode* root; /*Directorio raíz*/ struct inode* pwd; /* Directorio actual*/ }

9 Struct signal_struct Struct signal_struct {
int count ; /*Nº de descriptores de archivos asociados*/ struct k_sigaction[32] action; */ Tabla de funciones de desvío*/ }

10 Struct files_struct Struct files_struct {
int count; /*Nº de descriptores de archivos asociados*/ struct file* fd; /*Lista de descriptores de archivos abiertos*/ }

11 Struct file Struct file {
loff_t f_pos; /*Posición actual desde el inicio del fichero*/ struct file* f_next; /*Siguiente descriptor*/ struct file* f_prev; /*Anterior descriptor*/ }

12 Struct mm_struct Struct mm_struct {
int count; /*Número de referencias (procesos)*/ pgd_t pgd; /*Dirección de la tabla global de páginas utilizada por el proceso*/ unsigned long start_code; */Inicio del código del proceso en memoria*/ unsigned long end_code; /*Fin del código del proceso en memoria*/ unsigned long start_data; /*Inicio del segmento de datos*/ unsigned long end_data; /*Fin del segmento de datos*/ }

13 Struct namespace Struct namespace { int count;
struct vfsmount* root; /*Sistema de ficheros sobre el que está el proceso*/ }

14 Funcionamiento Obtención del proceso a terminar Comprobaciones previas
Informar de que el proceso está terminado Eliminar su temporizador Libera la memoria asociada al proceso Elimina cualquier semáforo pendiente Libera los ficheros asociados al proceso Libera los directorios raíz y actual del proceso Libera la información del sistema de ficheros Libera las acciones asociadas a las señales pendientes Elimina el hilo actual vinculado al proceso Desvincula la terminal asociada al proceso Acciones sobre el ámbito de ejecución Almacenamiento del código de retorno Advertencia al padre de la finalización de uno de sus hijos Cambio de contexto

15 do_exit void do_exit(long code) {
struct task_struct *tsk = current; //Obtenemos el proceso //Hacemos algunas comprobaciones antes de proceder if (in_interrupt()) /*Si el sistema está en una interrupción*/ panic(“aiee, kiling interrupt handler!”); if (!tsk->pid) /*¿Matar un proceso con pid 0? tarea inactiva*/ panic(“Attempted to kill the idle task!”); if (tsk->pid==1) /*¿Matar el proceso init?*/ panic(“Attempted to kill init!”); ….

16 do_exit void do_exit() { ….
tsk->flags |= PF_EXITING; /*Informa de que el proceso está terminado*/ del_timer_sync(&tsk->real_timer); / *Elimina su temporizador de la lista*/ __exit_mm(tsk); /*Libera el espacio de direccionamiento del proceso*/ lock_kernel(); /*Hecha cerrojo al kernel*/ sem_exit(); /*Si el proceso estaba esperando por un semáforo, lo elimina de la cola asociada a dicho semáforo*/ __exit_files(tsk); /*Libera los ficheros asociados al proceso*/

17 do_exit void do_exit() { ….
__exit_fs(tsk); /*Elimina toda información que relaciona el sistema de ficheros de un proceso*/ exit_namespace(); /*Borra las entradas y dependencias de los sistemas de ficheros, directorio raiz, etc*/ exit_sighand(tsk); /*Libera las acciones asociadas a las señales*/ exit_thread(); /*Elimina el hilo actual vinculado al proceso*/ if (current->leader) disassociate_ctty(1); /*Elimina el vínculo entre el proceso y la terminal correspondiente*/

18 do_exit void do_exit() { ….
put_exec_domain(tsk->exec_domain);/*Acciones sobre el ámbito de ejecución*/ /*Acciones sobre el formato del archivo ejecutable*/ if (tsk->binfmt && tsk->binfmt->module) __MOD_DEC_USE_COUNT(tsk->binfmt->module); tsk->exit_code = code; /*Almacena el código de retorno*/ exit_notify(); /*Establece el estado del proceso como TASK_ZOMBIE y Advierte al proceso padre de la finalización de uno de sus hijos*/ shedule(); /*Realiza un cambio de contexto*/ BUG(); }

19 Funciones complementarias
void __exit_mm(struct task_struct * tsk) { struct mm_struct * mm = tsk->mm; mm_release(); /*Libera la memoria*/ if (mm) { atomic_inc(&mm->mm_count); BUG_ON(mm != tsk->active_mm); task_lock(tsk); tsk->mm = NULL;/*Elimina toda la referencia a memoria*/ task_unlock(tsk); enter_lazy_tlb(mm, current, smp_processor_id()); mmput(mm);/*Devuelve al sistema los recursos asociados al proceso*/ }

20 Funciones complementarias
void __exit_files(struct task_struct *tsk) { /*Obtenemos los ficheros asociados al proceso*/ struct files_struct * files = tsk->files; if (files) /*Si tiene ficheros abiertos…*/ task_lock(tsk); tsk->files = NULL;/*…eliminamos los vínculos a los mismos*/ task_unlock(tsk); put_files_struct(files); }

21 Funciones complementarias
void __exit_fs(struct task_struct *tsk) { struct fs_struct * fs = tsk->fs; if (fs) /*…Si existe información de control de acceso*/ task_lock(tsk); tsk->fs = NULL;/*…la eliminamos*/ task_unlock(tsk); __put_fs_struct(fs); }

22 Funciones complementarias
void exit_namespace(struct task_struct *p) { /*Obtenemos la información del espacio de nombres asociado al descriptor del proceso*/ struct namespace *namespace = p->namespace; if (namespace) { task_lock(p); /*Se bloquea la tarea…*/ p->namespace = NULL; /*…Elimina la información*/ task_unlock(p); put_namespace(namespace); }

23 Funciones complementarias
void exit_sighand(struct task_struct *tsk) { /*Obtenemos los descriptores de acciones asociadas al proceso*/ struct signal_struct * sig = tsk->sig; spin_lock_irq(&tsk->sigmask_lock);/*Hecha cerrojo*/ if (sig) /*Si hay acciones pendientes…*/ tsk->sig = NULL;/*…las eliminamos*/ /*Decrementa el nº de procesos que apuntan a la tabla de funciones de desvío y se libera el espacio de memoria que ocupan*/ if (atomic_dec_and_test(&sig->count)) kmem_cache_free(sigact_cachep, sig); } tsk->sigpending = 0; /*Reiniciamos el número de acciones pendientes*/ flush_sigqueue(&tsk->pending); spin_unlock_irq(&tsk->sigmask_lock); /*Desbloquea el cerrojo*/

24 Llamada al sistema Wait
Es la llamada al sistema num. 114 Su función es la de hacer esperar a un proceso, por la finalización de uno de sus hijos. Implementada por la función sys_wait4 Contenida en el fichero fuente: kernel/exit.c

25 Interfaz sys_waitpid Función que se mantiene por compatibilidad, lo único que hace es llamar a sys_wait4 con los mismo parámetros.

26 Ejemplo de uso /*Programa de usuario*/ void main () { fork (); ...
wait(pid); } Cuando el proceso padre invoca al wait,… …detiene su ejecución hasta que el proceso hijo con el pid especificado,… ...finaliza, haciendo una llamada al sistema por medio del exit... ... o bien termina la ejecución de su código

27 Interfaz sys_wait4 Parámetros Valor de retorno
pid_t pid /* identificador del proceso por el que se va a esperar*/ unsigned int* stat_addr /* Dirección donde se copiará el estado de finalización del hijo*/ int options /* Define el comportamiento de sys_wait4*/ struct rusage* ru /* Dirección donde se indica la información de recursos usados por el proceso a esperar*/ Valor de retorno Devuelve el código de retorno del proceso hijo por el cual se espera, en forma de entero

28 Interfaz sys_wait4 El valor que tenga el parámetro PID tiene los siguientes significados: < -1 : Esperar por cualquier hijo cuyo ID de grupo sea igual al valor del pid (con el signo cambiado). -1 : Esperar por el primer hijo que termine. 0 : Esperar por cualquier hijo cuyo identificador de grupo sea igual al pid del proceso llamador (padre). > 0 : Esperar por los hijos cuyo pid es el indicado.

29 Descriptores de ficheros
Struct task_struct { pid_t pid; /*identificador de proceso*/ pid_t pgrp; /*identificador de grupo*/ wait_queue_head_t wait_chldexit; /*referencia a la cola de espera*/ volatile long state; /*estado actual del proceso*/ int exit_code; /*codigo de salida*/ int exit_signal; /*señal de salida*/ struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_osptr; /*puntero al padre original, al padre actual, al hijo y al hermano mas viejo*/ }

30 Descriptores de ficheros
State puede tener 5 valores: TASK_RUNNING: El proceso está en ejecución o esperando para ser ejecutado. TASK_INTERRUPTIBLE: El proceso se encuentra suspendido a la espera de que ocurra algún evento. TASK_UNINTERRUPTIBLE: Igual que el estado anterior pero una señal no despertará al proceso. TASK_STOPPED: La ejecución del proceso ha sido interrumpida al recibir una señal SIGSTOP, SIGTSTP, SIGTTIN o SIGTTOU. TASK_ZOMBIE: El proceso ha terminado de ejecutarse pero está esperando a que el padre haga un wait() (o muera).

31 Funcionamiento Verifica que las opciones son válidas.
Añade el proceso actual a la cola de procesos en espera. Para cada uno de los hijos del proceso: Busca un proceso hijo con el pid correspondiente Comprueba si es clónico o no Pregunta por el estado del proceso Pone el valor de retorno correspondiente. Saca el proceso actual de la cola de espera. Devuelve el valor de retorno.

32 sys_wait4 /*Verifica que las opciones son válidas.*/ ….
if(options & ~(WNOHANG|WUNTRACED|__WCLONE)) return -EINVAL; /*Si las opciones no son las esperadas, devuelve el valor “Argumento no válido” (EINVAL) WNOHANG : salir inmediatamente si no termina ningún hijo. WUNTRACED : si el hijo está detenido y su estado es desconocido se pasa al próximo hijo. _WCLONE : si se indica sólo se espera por los hijos clónicos, si no es así, por los que no lo son (un hijo clónico es aquel que no envía ninguna señal al padre salvo SIGCHLD hasta que finaliza)*/

33 sys_wait4 /*Añade el proceso actual a la cola de procesos en espera, identificado por el campo wait_chldexit.*/ …. add_wait_queue(&current->wait_chldexit,&wait); repeat: /*Para cada uno de los hijos del proceso*/ for (p = current->p_cptr ; p ; p = p->p_osptr)

34 sys_wait4 /*Busca un proceso hijo con el pid correspondiente*/ …
if (pid>0) { if (p->pid != pid) //¿Distinto pid? continue; } else if (!pid) { //Si es cero if (p->pgrp != current->pgrp) } else if (pid != -1) { //Si es distinto a -1 if (p->pgrp != -pid) //si pid de grupo es distinto a -pid } ...

35 sys_wait4 /*Comprueba si es clónico o no*/ …
if (((p->exit_signal != SIGCHLD) ^((options & __WCLONE) != 0)) && !(options & __WALL)) continue; /*Pregunta por el estado del proceso*/ switch (p->state) {

36 sys_wait4 …. case TASK_STOPPED:
if (!p->exit_code) //Si código de salida es cero continue; // pasa a otro hijo /* Se comprueba la bandera WUNTRACED*/ if (!(options & WUNTRACED) && !(p->ptrace & PF_PTRACED)) continue; /*si ru no es nulo, calcula la cantidad de recursos consumidos por el proceso actual y sus hijos, si no pone retval a cero*/ retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;

37 sys_wait4 /*Copia el estado de finalización del hijo*/ ….
if (!retval && stat_addr) retval = put_user((p->exit_code << 8) | 0x7f, stat_addr); /*Antes de salir resetea el código de salida*/ if (!retval) { p->exit_code = 0; retval = p->pid; } /*saca el proceso actual de la cola de espera*/ goto end_wait4;

38 sys_wait4 …. case TASK_ZOMBIE:
/*Actualización de la información que tiene el padre sobre el tiempo de usuario y del sistema usados por sus hijos*/ current->times.tm_cutime += p->times.tms_utime + p->times.tms_cutime; current->times.tm_cstime += p->times.tms_stime + p->times.tms_cstime; /*si ru no es nulo, calcula la cantidad de recursos consumidos por el proceso actual y sus hijos, si no pone retval a cero*/ retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;

39 sys_wait4 /*Copia el estado de finalización*/
if (!retval && stat_addr) retval = put_user(p->exit_code, stat_addr); /*Si el valor de retorno es > 0 vamos a end_wait4*/ if (retval) goto end_wait4; retval = p->pid; //asignamos al valor de retorno el pid del hijo /*Se comprueba que el padre sea el padre original del proceso*/ if (p->p_opptr != p->p_pptr) { //si no es asi… REMOVE_LINKS(p); //eliminamos los enlaces del hijo p->p_pptr = p->p_opptr; //restauramos el padre original SET_LINKS(p); //restauramos los enlaces do_notify_parent(p, SIGCHLD); //notificación al padre del cambio

40 sys_wait4 …. }else release_task(p); //libera la tabla de tareas del hijo goto end_wait4; default: //En cualquier otro caso busca el siguiente hijo continue; } //end switch } //end for } while (tsk != current); //end repeat

41 sys_wait4 /*Si existe algún proceso hijo con el pid indicado*/ ….
if (flag) { retval = 0 ; if (options & WNOHANG) /*Si WNOHANG activo sale directamente*/ goto end_wait4; /*Pone el valor de retorno a -ERESTARTSYS (La llamada al sistema ha sido interrumpida por una señal; no se ha leído nada)*/ retval = -ERESTARTSYS; /*Si el proceso actual tiene señales pendientes por tratar lo saca de la cola de espera*/ if (signal_pending(current))

42 sys_wait4 /*En caso contrario hace un cambio de contexto*/ schedule();
/*Se repite el proceso desde el principio*/ goto repeat; } /*Si no existe ningún proceso hijo, se devuelve -ECHILD (El proceso o grupo de procesos indicado no existe o no es hijo del proceso que llamó a la función) */ retval = -ECHILD; /*Se suprime el proceso actual de la cola de espera.*/ end_wait4: current->state = TASK_RUNNING; //pasa a estado de ejecución remove_wait_queue(&current->wait_chldexit,&wait); return retval;


Descargar ppt "Llamadas al Sistema EXIT y WAIT"

Presentaciones similares


Anuncios Google