Your SlideShare is downloading. ×
2 gestion de memoria en minix 3
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

2 gestion de memoria en minix 3

657
views

Published on


0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
657
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
25
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Gestión de memoria Minix 3 • 4 Gestión de memoria y procesos de usuario 4.1 Organización de la memoria (Tanenbaum 4.7.1) 4.2 Tratamiento de mensajes (Tanenbaum 4.7.2) 4.3 Estructuras de datos y algoritmos del Gestor de Procesos. (Tanenbaum 4.7.3) 4.4 Las llamadas al sistema fork, exit, y wait (Tanenbaum 4.7.4) 4.5 La llamada al sistema execve (Tanenbaum 4.7.5) 4.6 La llamada al sistema brk (Tanenbaum 4.7.6) 4.7 Tratamiento de señales (Tanenbaum 4.7.7) 4.8 Otras llamadas al sistema (Tanenbaum 4.7.8)Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 1 Escuela Universitaria de Informática - Universidad Politécnica de Madrid. 1
  • 2. Gestión de memoria Minix 3 Visión general •No utiliza paginación Modo usuario •Posible activación del uso de Intercambio •Comunicación por paso de mensajes Gestor de •Implementa la estrategia de asignación de memoria: Procesos Qué procesos residen en memoria y dónde •Dos funciones básicas: • Gestión de laTabla de procesos y de la lista de huecos • Implementación de las llamadas al sistema: fork, wait, execve, exit, brk, getpid, signal, kill, alarm, pause, getuid, getgid, setuid, setgid… Modo supervisor Núcleo •Implementa el mecanismo de asignación de memoria: de Minix Copia de mapas de memoria Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 2 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.La gestión de memoria en Minix 3 es simple. En primer lugar, no se utiliza paginación enabsoluto y en segundo lugar, aunque el código fuente completo incluye la posibilidad deluso de intercambio de memoria (“swapping”), por simplicidad, no se estudiará esta opción,ya que en la actualidad, la cantidad de memoria disponible en los sistemas, hace que en lapráctica, ésta sea raramente necesaria.El Gestor de Procesos (“Process Manager”) es el proceso de Minix que se encarga degestionar la memoria así como de manejar las llamadas al sistema relacionadas con lagestión de procesos. Algunas como “fork, exec y brk” muy relacionadas con la gestión dememoria, otras relacionadas con señales, y otras con características de los procesos,como el usuario y grupo propietario, tiempos de uso, etc. En cuanto a las estructuras dedatos gestionadas, destacan la Tabla de Procesos, con sus campos específicos y la Listade Huecos, la cual mantiene los huecos de memoria libres, ordenados ascendentementepor dirección de memoria. Sin el uso de Intercambio, la posición en memoria de unproceso no cambia durante toda su ejecución y tampoco aumenta o disminuye suasignación de espacio. Esta estrategia, aunque discutible, obedece principalmente a tresfactores: 1) El deseo de mantener el sistema sencillo, 2) La arquitectura original del IMBPC (Intel 8088) y 3) Conseguir una fácil portabilidad a otros sistemas con distintohardware.Hay que señalar un aspecto que diferencia a Minix de muchos otros sistemas operativos.El GP no es parte del núcleo (kernel), si no que es un proceso que corre en el espacio deusuario y se comunica con el núcleo mediante el mecanismo estándar del paso demensajes. Esto permite separar la estrategia del mecanismo de asignación de memoria.La decisión de qué proceso y dónde se ubicará en memoria (estrategia) esresponsabilidad del GP. El establecimiento de los mapas de memoria (mecanismo) lo llevaa cabo la Tarea del Sistema, la cual forma parte del núcleo. 2
  • 3. Gestión de memoria Minix 3 4.1 Organización de la memoria (1) Fichero ejecutable en disco Direcciones Altas → Símbolos (opcional) Datos (inicializados) Pila Código (text) Prog. B gap Segmento Cabecera I+D Separados Datos+bss Codigo Segmento • Bit de I+D juntos o separados Pila • Tamaños de memoria: Prog. A gap Total, Código, Datos, y BSS I+D juntos Segmento (El tamaño de memoria total en I+D juntos Datos+bss comprende la cantidad de memoria total necesaria para el proceso. En I+D separados, Código éste, no incluye el tamaño del código) Minix Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 3 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.En Minix es posible compilar los programas para que éstos usen espacios de códigos y datos (I+D)juntos o separados. Con espacios I+D juntos todas las partes de un proceso, código (text), datos ypila, comparten un mismo bloque de memoria (que para el procesador INTEL será un segmento).Este bloque será asignado o liberado como un todo. Con espacios I+D separados, las partes decódigo, datos y pila de un proceso se agrupan en dos bloques (o segmentos para INTEL). En elprimer bloque se ubica únicamente el código. En el otro bloque se ubican los datos y la pila (con unespacio dinámico entre ellos que denominaremos ‘gap’). Estos dos bloques o segmentos puedenser asignados y/o liberados de forma independiente. Por ejemplo, en la llamada al Sistema “fork”, seha de asignar la misma cantidad de memoria que usa el padre para el hijo. Si se utilizan espaciosI+D juntos, el proceso es simple, se asigna un único bloque de igual tamaño que tiene el padre parael hijo. Si se utilizan espacios I+D separados, el bloque de código se puede compartir entre el padrey el hijo y por tanto no se tiene que asignar. Sólo se requiere asignar un bloque nuevo de igualtamaño que el del padre para el hijo, conteniendo las áreas de datos y pila (mas gap).Minix conoce el número de procesos que están usando el mismo segmento de código en unmomento dado. Al finalizar un proceso siempre se libera su bloque de datos y pila (segmento deINTEL). El bloque (segmento de INTEL) de código sólo se liberaría, si éste bloque pasara a lasituación de no ser usado por ninguno otro proceso.Los ficheros ejecutables en disco, aparte del código y datos inicializados, incorporan opcionalmenteuna tabla de símbolos (para depuración), y también, de forma obligatoria, una cabecera coninformación sobre las necesidades de memoria para las distintas partes del proceso, así como de lanecesidad total de memoria, además de si el uso de espacios I+D es juntos o separados. Si losespacios son juntos, el tamaño de la memoria total se refiere a la cantidad de memoria total querequiere el proceso (incluye datos+bss+gap+pila). En espacios I+D juntos, la cantidad de memoriatotal incluye además el código. Por ejemplo, si un fichero con espacios I+D juntos tiene 4KB decódigo, 2KB de datos+bss, 1KB de pila y 40KB memoria total, el gap sería de 33KB. Si fueranseparados el gap sería de 37 KB.El área BSS son datos del proceso que no requieren inicialización y por ello no se guardan en elarchivo ejecutable. 3
  • 4. Gestión de memoria Minix 3 4.1 Organización de la memoria (2) Asignación de memoria. · Con las llamadas: Gestor de fork: la misma cantidad que al padre Procesos execve: la cantidad indicada en la cabecera del fichero ejecutable Liberación de memoria. · Cuando un proceso muere, bien mediante exit ó por la llegada de una señal cuyo tratamiento sea matar al proceso receptor. · Con execve se libera si la llamada tiene éxito. Dir. Altas → Hijo de A Prog. C Mapas de memoria: (I+D juntos) Prog. B Prog. B (a) Originalmente, Prog. B (b) Después de fork, (c) Después de execv del hijo. Prog. A Prog. A Prog. A Minix Minix Minix (a) (b) (c) Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 4 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.En las operaciones normales de MINIX 3 se asigna memoria a un proceso sólo en dos ocasiones:Con la llamada “fork”, en la que asigna la cantidad de memoria que precisa el hijo y con la llamada“execve”, en la que se devuelve la memoria usada por la vieja imagen a la lista de huecos libres yse asigna memoria para la nueva imagen.La liberación de memoria ocurre en dos ocasiones: a) Cuando un proceso muere, bien sea por lallamada “exit” o la recepción de una señal y b) Durante la llamada “execve” si ésta tiene éxito.En la llamada “fork”, dependiendo de si los espacios I+D son juntos o separados, se asignamemoria para el proceso hijo de una forma u otra. Con espacios juntos, la memoria nuevaasignada constituirá un solo bloque (segmento de Intel), del mismo tamaño que el del padre, elcual se corresponde con la memoria total utilizada por el padre, es decir, la suma de los tamañosdel código, datos, gap y pila. Con espacios separados, se asigna un nuevo bloque para el hijo deigual tamaño que el de padre, pero este bloque (segmento) contiene únicamente las áreas dedatos, gap y pila. El bloque de código (segmento) en cambio, no se asigna, ya que puede ser y es,compartido con el padre.En la llamada “execve” se asigna al proceso la cantidad de memoria indicada en la cabecera delfichero ejecutable, teniendo en cuenta si los espacios son juntos o separados, tal y como ya se hacontado. Hay que tener en cuenta en esta llamada, que si los espacios son separados se complicaun poco la gestión, ya que al liberar la vieja imagen, tendrá que tenerse en cuenta si el bloque decódigo está siendo compartido por otro proceso, en cuyo caso no se liberaría éste último. Esteproblema no ocurre con espacios juntos, ya que al no haber bloques de código compartidos,siempre que se libera la imagen de memoria vieja, se libera de forma completa, ya que éstaconstituye un único segmento (o bloque).Un problema similar ocurre con espacios separados cuando un proceso muere. También se ha detener en cuenta si el bloque (segmento) de código está siendo usado por otro proceso o no, paraliberarlo o no, en consecuencia.
  • 5. Gestión de memoria Minix 3 4.2 Tratamiento de mensajes (1) Tipo mensaje Parámetros de entrada Valor devuelto fork ninguno Pid hijo y 0 al hijo exit exit status Si éxito, ninguna wait ninguno Status waitpid Identificador de proceso y flags Status brk Nuevo tamaño Nuevo tamaño exec Puntero pila inicial Si éxito, ninguna kill Identificador proceso y señal Status alarm Nº segundos a esperar Tiempo que queda pause ninguno Si éxito, ninguna sigaction Nº de señal, accion, accion ant. Status sigsuspend Mascara de señal Si éxito, ninguna sigpending ninguno Status sigprocmask Cómo, set y set anterior Status sigreturn contexto Status getuid ninguno Uid y uid efectivo getgid ninguno Gid y gid efectivo getpid ninguno Pid y pid del padre Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 5 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.El Gestor de Procesos, al igual que el resto de componentes de Minix 3, está dirigido por mensajes.Después de la inicialización, éste entra en el bucle principal, el cual consiste básicamente en:Esperar un mensaje, realizar la petición contenida en el mismo y enviar un mensaje de respuesta.Los mensajes recibidos pertenecen a dos categorías, mensajes de procesos de usuario y mensajesde notificación del Sistema. Siendo estos últimos usados para la comunicación de alta prioridadentre el “kernel” y los gestores (servidores de Minix).La mayoría de los mensajes recibidos por el GP resultan de llamadas al Sistema generadas por losprocesos de usuario. Estos mensajes son los que se muestran en la transparencia.También sucede, como cabria esperarse, que la mayoría de las llamadas al Sistema que trata elGestor de Procesos están relacionadas con la memoria, procesos o señales, no obstante, algunasque no lo están, como por ejemplo “time, stime, ptrace, etc”, simplemente se han incluido aquíporque el Gestor de Ficheros ya era bastante grande y complejo.El mensaje “reboot” tiene efectos en todo el S.O., pero su principal trabajo es enviar señales determinación a todos los procesos de forma controlada, por eso lo trata el Gestor de Procesos. Lomismo sucede con el mensaje “svrctl” que activa y desactiva el intercambio. Los mensajes“getsysinfo, getprocnr, memalloc, memfree, y getsetpriority” no están pensados para procesos deusuario ordinarios, y no forman parte de POSIX. En un sistema monolítico, las operaciones que realizan el tratamiento de estos mensajes estáncompiladas en el kernel como llamadas a función, pero en Minix 3, partes que normalmente sonconsideradas del Sistema Operativo, corren en espacio de usuario. Algunas de ellas hacen pocomás que implementar un interfaz a una llamada al “kernel”, término que podemos usar parapeticiones de servicio del kernel vía “Tarea del Sistema”. 5
  • 6. Gestión de memoria Minix 3 4.2 Tratamiento de mensajes (2) Tipo mensaje Parámetros de entrada Valor devuelto setuid Nuevo uid Status setgid Nuevo gid Status setsid Nuevo sid Grupo de proceso getpgrp Nuevo gid Grupo de proceso time Puntero al lugar donde poner el tiempo actual Status stime Puntero al tiempo actual Status times Puntero a buffer para tiempos del proceso e hijo Tiempo desde el arranque ptrace petición, pid, dirección y datos Status reboot Cómo (halt, reboot o panic) Si éxito, ninguna svrctl Petición, datos, (depend. Func.) Status getsysinfo Petición, datos, (depend. Func.) Status getprocnr ninguno Nº de proceso memalloc Tamaño, puntero a dirección Status memfree Tamaño, dirección Status getpriority Pid, tipo y valor Prioridad setpriority Pid, tipo y valor Prioridad gettimeofday ninguno Tiempo Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 6 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Existe una estructura de datos fundamental para el procesado de los mensajes: La tabla“call_vec”, la cual contiene los punteros a los procedimientos que tratan los diferentesmensajes.Cuando llega un mensaje al Gestor de Procesos (en el bucle principal), se extrae el tipode mensaje y se pone en la variable global “call_nr”. Este valor -el tipo-, se usa comoíndice de la tabla “call_vec” para encontrar el puntero al procedimiento que tratará elmensaje recién llegado, para a continuación, hacer una llamada al mismo y ejecutar lallamada al Sistema.El valor devuelto por este procedimiento se incluye en un mensaje que se le envía alproceso llamante como respuesta, informándole así de la conclusión de la llamada y deléxito o fracaso (código de error) de la misma. 6
  • 7. Gestión de memoria Minix 3 4.3 Estructuras de datos y algoritmos del Gestor de Procesos (1) /* -------------------------------- Tabla de procesos --------------------------------------- Esta tabla tiene una entrada por proceso. Contiene toda la información de gestión de procesos para cada proceso. Entre otras cosas, define los segmentos de código, datos y pila. Valores uids y gids, y varios flags. */ EXTERN struct mproc { struct mem_map mp_seg[NR_LOCAL_SEGS]; /* mapa del código, datos y pila */ char mp_exitstatus; /* guarda status cuando el proceso acaba */ char mp_sigstatus; /* guarda nº señal de procesos matados */ pid_t mp_pid; /* identificador de proceso */ pid_t mp_procgrp; /* pid de grupo de procesos (usado para señales)*/ pid_t mp_wpid; /* pid del proceso que se está esperando */ int mp_parent; /* indice del proceso padre */ /* Tiempos de usuario y sistema de los hijos. Contabilizado en ‘exit’ del hijo. */ clock_t mp_child_utime; /* tiempo de usuario acumulado de los hijos */ clock_t mp_child_stime; /* tiempo de sistema acumulado de los hijos */ /* uids y gids reales y efectivos. */ uid_t mp_realuid; /* uid real del proceso */ uid_t mp_effuid; /* uid efectivo del proceso */ gid_t mp_realgid; /* gid real del proceso */ gid_t mp_effgid; /* gid efectivo del proceso */ /* Identificacion de fichero para compartir. */ ino_t mp_ino; /* nº de inodo de fichero */ dev_t mp_dev; /* nº de dispositivo del sistema de ficheros */ time_t mp_ctime; /* cambio de tiempo en inodo */ . . . /* Continua. Sig. Transp…*/ Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 7 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Existen dos estructuras básicas que usa el Gestor de Procesos: La tabla de procesos(mantenida en la variable “mproc”) y la tabla de huecos. Algunos de los campos de la tablade procesos los necesita el “kernel”, otros el Gestor de Procesos y otros el Gestor deFicheros. En Minix 3, cada una de estas tres partes del S.O. tiene su propia tabla deprocesos, en la que únicamente se tienen los campos que necesitan. Salvo algunasexcepciones, las entradas en la tabla se corresponden exactamente. Así la posición ‘k’ dela tabla del G.P. se refiere al mismo proceso que la posición ‘k’ de la tabla del G.F..Cuando se crea o destruye un proceso, las tres partes actualizan sus tablas para reflejar lanueva situación consistentemente. Las excepciones son procesos que no son conocidosfuera del “kernel”, como las Tareas de Reloj y de Sistema, o bien los “falsos” procesosIDLE y KERNEL (ocupan entrada pero no tienen código). En la tabla del “kernel”, estasexcepciones tienen asignados números negativos de entrada. Estas entradas no existenni en el G.P. ni en el G.F.. Así, lo dicho anteriormente acerca de la posición ‘k’, esestrictamente cierto para valores mayores o iguales a cero. Otros procesos de Minix comoel Gestor de Procesos y el Gestor de Ficheros tienen asignadas las entradas 0 y 1respectivamente en todas las tablas.Un campo a destacar de la tabla de procesos del G.P. es el vector “mp_seg”, el cual tienetres elementos para expresar los segmentos de código, datos y pila (no confundir eltérmino segmento de Minix, que hemos denominado anteriormente ‘bloque’, con el mismotérmino segmento de INTEL). Cada elemento a su vez, es una estructura que contiene lasdirecciones virtual y física, así como la longitud de cada segmento, todo ello expresado en‘clics’. El tamaño de un ‘clic’ es dependiente de la implementación, siendo en Minix-3 de1024 bytes. Todos los segmentos ocupan un número entero de clics y empiezan siempreen una dirección múltiplo del tamaño del ‘clic’. 7
  • 8. Gestión de memoria Minix 3 4.3 Estructuras de datos y algoritmos del Gestor de Procesos (2) /* Continuación anterior transparencia */ . . . /* Información de manejo de señales. */ sigset_t mp_ignore; /* 1 significa ignorar la señal, 0 no */ sigset_t mp_catch; /* 1 significa capturar la señal, 0 no */ sigset_t mp_sig2mess; /* 1 significa transformar en mensaje de notificación */ sigset_t mp_sigmask; /* señales a bloquear */ sigset_t mp_sigmask2; /* copia segura de ‘mp_sigmask’ */ sigset_t mp_sigpending; /* señales pendientes de manejar */ struct sigaction mp_sigact[_NSIG + 1]; /* como en ‘sigaction(2)’ */ vir_bytes mp_sigreturn; /* dirección de la librería C funcion ‘__sigreturn’ */ struct timer mp_timer; /* temporizador ‘watchdog’ para ‘alarm(2)’ */ /* compatibilidad con anteriores versiones para señales. */ sighandler_t mp_func; /* todas las señales vectorizadas a una única func. de usuario */ unsigned mp_flags; /* flag bits */ vir_bytes mp_procargs; /* puntero a argumentos en pila iniciales del proceso */ struct mproc *mp_swapq; /* cola de procesos esperando intercambio */ message mp_reply; /* mensaje de respuesta para enviar */ /* Prioridad de planificación. */ signed int mp_nice; /* ‘nice’ es PRIO_MIN..PRIO_MAX, estándard 0. */ char mp_name[PROC_NAME_LEN]; /* nombre de proceso */ } mproc[NR_PROCS]; Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 8 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.El vector “mp_seg” permite traducir las referencias de direcciones virtuales a direccionesfísicas. Dada una dirección virtual y el proceso al que pertenece, es sencillo verificar si setrata de una dirección que cae dentro del mapa del proceso, y en ese caso traducirla adirección física de memoria. Más adelante se muestra una transparencia con un ejemplode uso de este vector.La tabla “mproc” mantiene también otra información necesaria para la gestión de loprocesos. Esta incluye identificadores de proceso, los uid’s y gid’s (identificadores deusuario y grupo, reales y efectivos), información sobre las señales, y el estado definalización si el proceso quedara en estado “zombie” (cuando muere y su padre no estáesperando por él). Hay campos para un temporizador para “sigalarm” y campos paracontabilizar los tiempos de usuario y sistema empleados por los procesos hijos. (enanteriores versiones de Minix esto último era responsabilidad del kernel).La mayoría de los campos están descritos adecuadamente en su comentario. Algunoscampos tratan sobre el manejo de señales, “mp_ignore, mp_catch, mp_sig2mess,mp_sigmask, mp_sigmask2, y mp_sigpending” son mapas de bits (bitmaps), en los quecada bit representa una de las señales. Actualmente hay 22 señales definidas, aunquealgunas no están soportadas, según permite el estándar POSIX. La señal 1 secorresponde con el bit menos significativo. En cualquier caso, POSIX requiere funcionesestándar para añadir o quitar miembros del conjunto de señales representado en estos“bitmaps”, tal que su manipulación sea transparente en sus detalles al programador. Elarray “mp_sigact” es importante para el manejo de señales, tiene un elemento para cadatipo de señal del tipo “estructura sigaction”.El campo “mp_flags” se usa para guardar un conjunto variado de bits. El campo es unentero sin signo, de 16 bits en un procesador de baja capacidad y de 32 procesadoressuperiores. 8
  • 9. Gestión de memoria Minix 3 4.3 Estructuras de datos y algoritmos del Gestor de Procesos (3) Tabla de procesos Lista de huecos Gestor de Procesos Dirección virtual, física y tamaño de cada segmento Proceso “i” interno, medido todo ello campo en “clics”. ‘mp_seg’ (1 clic = 1024 bytes) (datos en hexadecimal) 210 KB (0x34800) Virtual Física Long. Virtual Física Long. Pila Código 0x00 0xC8 0x00 Código 0x00 0xC8 0x03 208 KB (0x34000) Datos 0x00 0xC8 0x07 Datos 0x00 0xCB 0x04 207 KB (0x33C00) Pila 0x08 0xD0 0x02 Pila 0x05 0xD0 0x02 Datos I+D juntos I+D separados 203 KB (0x32C00) Código Respecto a dir. fisica de Respecto a la dir. fisica 200 KB (0x32000) datos: D0 – C8 = 08 de datos: D0 - CB = 05 Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 9 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.El método usado para registrar la ubicación en memoria de los procesos se puede ver en latransparencia. En este ejemplo se muestra un proceso de 3 KB de código, 4 KB de datos, 1 KB dehueco (gap) y una pila de 2 KB.Las direcciones virtuales de los segmentos de código y datos son siempre 0. El tamaño delsegmento de código en el caso de I+D juntos es siempre 0 (ya que el código está en el segmentode datos, es como decir que no hay segmento de código). El tamaño del segmento de datos, eneste mismo caso, tiene la suma de los tamaños de código y datos (3+4=7).La dirección virtual de la pila se calcula siempre como la diferencia entre las direcciones físicas delcomienzo de la pila y el comienzo del segmento de datos (que en el caso de I+D juntos coincidetambién con el comienzo del segmento de código). Cuando un proceso hace referencia a ladirección virtual 0, tanto en el espacio de código como en el de datos, se usará la dirección física decomienzo correspondiente al segmento referido, es decir la dirección 0x32000 (= 200 KB, = 0xC8clic), si es en el espacio de código, ó 0x32C00 (= 203 KB, = 0xCB clic), si es en el espacio de datos.Dada una dirección virtual y el espacio al que pertenece, es fácil determinar si dicha dirección virtuales legal o no (que pertenezca al segmento), y si es legal, determinar cual es su dirección física.Nótese que la dirección virtual en la que comienza la pila depende de la cantidad total de memoriareservada para el proceso. Si se usara el comando “chmem” para modificar la cabecera del ficheropara dotar al proceso de más espacio dinámico (más gap), la siguiente vez que se ejecutara, la pilacomenzaría en una dirección virtual más alta. Si la pila creciera 1 clic, la tripleta de pila [0x8, 0xD0,0x2] pasaría a ser [0x7, 0xCF, 0x3], esto reduciría a la nada el gap si no se modificase la cantidadtotal de memoria del proceso (10 KB). 9
  • 10. Gestión de memoria Minix 3 4.3 Estructuras de datos y algoritmos del Gestor de Procesos (4) Gestor de Estructuras ‘hole’ en lista ordenada Procesos por dirección base ascendente. Prog. C hole_head Prog. B Lista de huecos del GP Prog. A Dirección base Puntero al siguiente Minix Tamaño del hueco (en clics) ‘h_base’ (en clics) ‘h_len’ ‘h_next’ #define NR_PROCS 100 #define NR_HOLES (2*NR_PROCS+4) /* max elementos en tabla ‘hole’*/ #define NIL_HOLE (struct hole *) 0 PRIVATE struct hole { Declaracion en ‘C’ de struct hole *h_next; /* puntero al siguiente */ la estructura de datos phys_clicks h_base; /* comienzo del hueco */ para la lista de huecos phys_clicks h_len; /* longitud del hueco */ } hole [NR_HOLES]; PRIVATE struct hole *hole_head; /* puntero al primer hueco */ PRIVATE struct hole *free_slots; /* primera posición sin usar */ Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 10 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.La otra estructura de datos principal del Gestor de Procesos es la tabla de huecos, la cualmantiene una lista de todos los huecos de memoria en orden ascendente de dirección dememoria. Los huecos entre los datos y pila de un proceso no son considerados huecos, ya que yahan sido asignados a los procesos, y por ello consecuentemente, no figuran en la lista dehuecos.Tanto la dirección base del hueco como el tamaño del mismo vienen expresados en ‘clics’en vez de en bytes. La razón de ello es porque es mucho más eficiente. Por ejemplo, si seusan enteros de 16 bits para almacenar direcciones de memoria, con unidades de 1024bytes por clic, sería posible hacer referencia hasta 64 MB en vez de sólamente 64 KB. 10
  • 11. Gestión de memoria Minix 3 4.3 Estructuras de datos y algoritmos del Gestor de Procesos (5) 200 40 clics hole_head 20 C 30 clics free_slots 10 clics 300 10 B 20 clics 340 40 A Null 60 clics 20 clics 200 MINIX Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 11 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.La variable “hole_head” apunta al primer elemento del vector ‘hole’ (de 204 elementos),el cual contiene el primer hueco.La variable “free_slots” apunta al primer elemento “hole” libre (slot).“hole_head” establece el comienzo de la lista de huecos y ‘”free_slots” el de la lista deelementos “hole” (slots) que no están asociados a ningún hueco de memoria, es decir,libres. 11
  • 12. Gestión de memoria Minix 3 4.3 Estructuras de datos y algoritmos del Gestor de Procesos (5) Memoria clics 254 KB Null 0x0302 (1) D. Base Tamaño Prog. B Situación Inicial 0x02D0 0302 00FE de la memoria y lista de huecos 500 KB 0x00DC 00DC 01F4 (2) Prog. A 0x00B4 Situación tras Minix hole_head 0x0000 ubicar el programa ‘C’ de 100 KB’ (3) Memoria clics Memoria clics Situación tras 254 KB Null La muerte de los 0x0302 D. Base Tamaño Programas ‘B’ y ‘C’ Prog. B 0x02D0 0302 00FE 804 KB Null 400 KB 0x0140 D. Base Tamaño Prog. C 0x00DC 0140 0190 00DC 0324 0x00DC Prog. A 0x00B4 Prog. A 0x00B4 Minix hole_head Minix hole_head 0x0000 0x0000 Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 12 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Las principales operaciones en la lista de huecos son: a) Reservar una cantidad dememoria y b) Devolver una cantidad previamente asignada. Para reservar memoria, sebusca en la lista -que se halla ordenada ascendentemente por direcciones de memoria-,desde el principio en adelante, un hueco que satisfaga la necesidades de memoria. Unavez seleccionado el hueco, si el tamaño no fuese exacto, se reduciría el tamaño del mismoen la cantidad solicitada y el hueco permanecería en la lista con el nuevo tamaño residual.Si el tamaño fuese exacto, el hueco desaparecería de la lista. Este esquema es rápido ysimple pero sufre tanto de fragmentación interna (hasta 1023 bytes de posible desperdicio)como de fragmentación externa.Cuando un proceso finaliza, si se han usado espacios I+D juntos, su memoria se libera yse devuelve a la lista de huecos como un todo. Si los espacios son separados, elsegmento de datos se devuelve a la lista de huecos, pero la liberación del segmento decódigo dependerá de que no se encuentre otro proceso que lo esté compartiendo. Si seencontrara, éste no se liberaría. Los segmentos de código y datos no tienen porqué sercontiguos, y sería posible por tanto devolver dos regiones de memoria. Para cada regióndevuelta se comprueba si en su vecindad hay algún hueco, y si así fuera, se fusionaríandicho hueco o huecos con la región devuelta, quedando en la lista un único hueco detamaño suma de la región o regiones vecinas y la propia región devuelta. De este modonunca hay huecos adyacentes en la lista.En la transparencia se muestra un ejemplo de reserva y liberación de espacio de memoria.El tamaño del clic, como ya se ha dicho, es de 1024 bytes. Minix ocupa 180 KB, Losprogramas ‘A’, ‘B’ y ‘C’ ocupan 40 KB, 50 KB y 100 KB respectivamente, aunque estainformación se puede obtener fácilmente desde la figura. 12
  • 13. Gestión de memoria Minix 3 4.4 Las llamadas al sistema (Bucle principal GP, 1/4) PUBLIC int main() { /* Rutina “main” del Gestor de Procesos */ int result, s, proc_nr; struct mproc *rmp; sigset_t sigset; pm_init(); /* Inicializa tablas del Gestor de Procesos */ /* Este el el bucle principal : obtiene trabajo y lo hace, indefinidamente */ while (TRUE) { get_work(); /* Espera mensaje para el Gestor de Procesos */ /* Comprueba notificaciones del Sistema primero. Casos especiales */ if (call_nr == SYN_ALARM) { pm_expire_timers(m_in.NOTIFY_TIMESTAMP); result = SUSPEND; /* no responder */ } else if (call_nr == SYS_SIG) { /* señales pendientes */ sigset = m_in.NOTIFY_ARG; if (sigismember(&sigset, SIGKSIG)) (void) ksig_pending(); result = SUSPEND; /* no responder */ } /* Sino, si el nº de llamada al Sistema es válido, la lleva a cabo */ else if ((unsigned) call_nr >= NCALLS) { result = ENOSYS; /* Nº llamada erróneo */ } else { result = (*call_vec[call_nr])(); /* LLama a la función “do_...” */ } /* Envía respuesta de finalización al usuario */ if (result != SUSPEND) setreply(who_p, result); /* Continua . . . . . */ Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 13 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.El Gestor de Procesos se compila y monta de forma independiente del“kernel” y del Gestor de Ficheros, por tanto tiene su propia función “main”que comienza después de que el kernel haya finalizado su inicialización.Después de efectuar su propia inicialización, mediante “pm_init()”, seentra en un bucle, en el cual se llama a “get_work()”, para esperar algúnmensaje entrante. Entonces se llama a una de las funciones do_xxx(), pormedio de la tabla de punteros a función “call_vec” para llevar a cabo lapetición. Finalmente se envía una respuesta, si se requiere.Este escenario está algo simplificado. Mensajes de notificación puedenser enviados a cualquier proceso. Estos están identificados por valoresespeciales en el campo “call_nr”. En el código puede verse lacomprobación de estos mensajes y la acción especial que se toma en sucaso. También se comprueba que “call_nr” tenga un valor correcto, ya queaunque un valor incorrecto es improbable, la comprobación no es costosay se evita un error grave.Finalmente, aunque el comentario de la línea donde aparece “setreply”dice que se envía la respuesta de finalización, esto es algo máscomplicado. La función “setreply()” construye una respuesta en la entradade la Tabla de Procesos (TP) del proceso actual. Más adelante (siguientetransparencia) hay un bucle donde se recorre la TP y se comprueba si hayrespuestas (mensajes) pendientes de enviar y se envían, omitiéndoseaquellas que no pueden enviarse en ese momento. 13
  • 14. Gestión de memoria Minix 3 4.4 Las llamadas al sistema (Bucle principal GP. 2/4) /* Continuación …… */ swap_in(); /* Quizá un proceso pueda entrar en memoria (intercambio) */ /* Da salida a todos los mensajes pendientes de envío, incluyendo la respuesta a la llamada recien * hecha arriba. Los procesos no deben estar fuera de la memoria (“not swapped out”) */ for (proc_nr=0, rmp=mproc; proc_nr < NR_PROCS; proc_nr++, rmp++) { /* Mientras tanto, el proceso puede haber muerto por una señal (e.g. si una señal letal * pendiente hubiera sido desbloqueada) sin que el GP lo supiera. Si la entrada en la TP * está libre o como “zombie”, no se responde. */ if ((rmp->mp_flags & (REPLY | ONSWAP | IN_USE | ZOMBIE)) == (REPLY | IN_USE)) { if ((s=send(rmp->mp_endpoint, &rmp->mp_reply)) != OK) { printf("PM cant reply to %d (%s)n", rmp->mp_endpoint, rmp->mp_name); panic(__FILE__, "PM cant reply", NO_NUM); } rmp->mp_flags &= ~REPLY; } /* end-if*/ } /*end-for*/ } /*end-while*/ return(OK); } /*end-main*/ Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 14 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Otro punto a hacer notar es la llamada a “swap_in”. Esta llamada está vacía si laconfiguración de Minix no incluye “intercambio de memoria”. Pero si Minix se configurapara incluir todo el fuente con intercambio activado, es aquí donde se realiza lacomprobación de si un proceso puede ser intercambiado a memoria. 14
  • 15. Gestión de memoria Minix 3 Las llamadas al sistema (Bucle principal GP. 3/4) PRIVATE void get_work() /* Espera el siguiente mensaje y extrae información útil de él */ { if (receive(ANY, &m_in) != OK) panic(__FILE__,"PM receive error", NO_NUM); who_e = m_in.m_source; /* quién envió el mensaje */ if(pm_isokendpt(who_e, &who_p) != OK) panic(__FILE__, "PM got message from invalid endpoint", who_e); call_nr = m_in.m_type; /* Nº de llamada al Sistema */ /* ‘Slot’ (entrada en la tabla de procesos) del proceso llamador (caller). Se usa el ‘slot’ propio del Gestor de Procesos si es el kernel el que hace la llamada. Esto puede suceder en el caso de alarmas sincronas (CLOCK), o señales del kernel pendientes tipo evento (SYSTEM) */ mp = &mproc[who_p < 0 ? PM_PROC_NR : who_p]; /* mp es el puntero al ‘slot’ */ if(who_p >= 0 && mp->mp_endpoint != who_e) { panic(__FILE__, "PM endpoint number out of sync with source", mp->mp_endpoint); } /*end-if*/ } Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 15 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Los procedimientos “get_work” y “setreply” manejan de hecho, la recepción y envío demensajes respectivamente. El primero efectúa un pequeño truco para hacer parecer queun mensaje del kernel lo era en realidad del propio Gestor de Procesos, ya que el kernelno tiene una entrada (slot) propia en la tabla de procesos. La otra función no envía enrealidad la respuesta, simplemente la prepara, para que pueda ser enviada más tarde,tal y como ya se ha indicado. 15
  • 16. Gestión de memoria Minix 3Las llamadas al sistema (Bucle principal GP. 4/4)PUBLIC void setreply(proc_nr, result)int proc_nr; /* Proceso a responder */int result; /* Resultado de la llamada (normalmente OK, o nº error) */{/* Cumplimenta un mensaje de respuesta para ser enviado más tarde a un proceso de usuario. Las llamadas al Sistema pueden ocasionalmente rellenar otros campos, esto es únicamente para retornar el valor al bucle “main” y también establecer el flag “must send reply”. */ register struct mproc *rmp = &mproc[proc_nr]; if(proc_nr < 0 || proc_nr >= NR_PROCS) panic(__FILE__,"setreply arg out of range", proc_nr); rmp->mp_reply.reply_res = result; rmp->mp_flags |= REPLY; /* Respuesta pendiente */ if (rmp->mp_flags & ONSWAP) swap_inqueue(rmp); /* Se debe intercambiar el proceso, traer de vuelta a memoria */} Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 16 Escuela Universitaria de Informática - Universidad Politécnica de Madrid. 16
  • 17. Gestión de memoria Minix 3 4.4 Las llamadas al sistema, fork, exit y wait: (fork) Proceso Proceso de hijo Usuario ▪ Comprueba tabla de procesos llena ▪ Reserva memoria ▪ Avisa a la TS ▪ Informa a la ▪ Informa al para datos y pila para que copie TS del nuevo GF del nuevo del hijo el nuevo mapa proceso proceso ▪ Solicita copiar de memoria datos a la TS Gestor de Procesos ▪ Busca entrada libre SYS_NEWMAP en la TP para el hijo SYS_VIRCOPY Tell_fs(FORK,.) y copia la entrada del SYS_FORK padre en ella. ▪ Copia el nuevo ▪ Cumplimenta el nuevo mapa desde la mapa de memoria del TP del GP a la TP hijo en su entrada. del kernel ▪ asigna un nuevo ‘pid’ Tarea del para el hijo. Sistema ▪ Crea proceso hijo ▪ Crea proceso hijo ▪ Copia datos y pila Gestor de en su propia Tabla en su propia Tabla del padre a la imagen Ficheros de memoria del hijo Significado de las flechas: send_rec (…) flechas send (…) Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 17 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Cuando se crea un proceso la Tabla de Procesos (TP) debe ser actualizada, lo queincluye también a las TP’s del Kernel y Gestor de Ficheros (GF). El Gestor de Procesos(GP) coordina esta actividad. La creación de procesos se efectúa mediante “fork”, tal ycomo se muestra, a grandes rasgos, en la transparencia. Es difícil e inconveniente deteneruna llamada “fork” en curso, por lo que se han de hacer una serie de comprobaciones paraasegurar que la llamada no falla. En primer lugar (1) se comprueba que haya sitio en laTP. El GP lleva una contador de procesos creados, así es fácil saber si se puede crearuno nuevo. Si hay sitio en la TP (2) se reserva memoria para el nuevo proceso, (si I+Dseparados no se reserva espacio para el código). Si hubo éxito en la reserva la llamada“fork” no fallará, entonces (3) se rellena el espacio memoria reservado (copiando laimagen de memoria del padre). (4) Se ubica una nueva entrada en la TP y se rellenacopiándose de la entrada del padre, actualizando convenientemente los campos“mp_parent, mp_flags, mp_child_utime, mp_child_stime, (5) mp_seg (nuevo mapa dememoria), mp_exitstatus y mp_sigstatus” (algunos bits de “mp_flags” se heredan). (6) Seescoge un “pid”, este paso no es trivial; el “pid” empieza en 1 incrementándose hasta unvalor máximo de 30.000, cuando se alcanza este valor, se vuelve a empezar a partir del 2,comprobando que no esté en uso, si lo estuviera se incrementaría en 1 y se volvería acomprobar, y así sucesivamente hasta encontrar uno libre. (7) Se informa a las otraspartes de Minix (kernel y GF) del nuevo proceso creado, para que éstas a su vez puedanactualizar sus TP’s. Por último, (8) se prepara la respuesta, primero al proceso hijo conpid=0, y luego al padre, con el “pid” asignado al hijo. El orden en el que se realizan lasrespuestas dependerá de la posición que ocupen los procesos padre e hijo en la tabla deprocesos. Se envía primero el que ocupa una posición mas baja. 17
  • 18. Gestión de memoria Minix 3 4.4 Las llamadas al sistema, fork, exit y wait: (exit) Desaparece, Proceso No hay respuesta Proceso de padre Usuario ▪Contabiliza SI : --- “cleanup”--- tiempos de ▪Libera entrada en la TP Se desbloquea cpu al padre ▪decrementa contador ▪Notifica a procesos. ▪ Recorre TP: la TS del fin ▪Despierta al padre Para cada entrada: de ejecución devolviendole el pid Si es hijo hijo->parent = Init ¿ ALARMA ▪Solicita ▪Informa al ▪Informa a la TS del fin Si zombie & Init waiting PENDIENTE ? tiempos de GF del fin del proceso ¿ PADRE “cleanup” del hijo cpu a la TS del proceso EN WAIT ? Gestor de Procesos SYS_TIMES Tell_fs (EXIT) ▪Libera memoria del SYS_SETALARM SYS_EXIT SYS_NICE SI:Desactivar proceso. Segmento NO : ------------ de Datos + Pila y ▪Estado=zombie. segmento de Código ▪Envía SIGCHLD Tarea del si no está más en uso “sig_proc()” Sistema ▪Guarda en entrada de TP “exit_status” Gestor de ▪Desactiva ▪Detiene el Ficheros alarma proceso Significado de las flechas: send_rec (…) flechas send (…) Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 18 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Un proceso termina totalmente cuando suceden dos cosas: (1) El proceso ha finalizado (por “exit” orecepción de una señal), y (2) su padre estaba esperando en un “wait”. Un proceso que hafinalizado, pero cuyo padre no ha efectuado “wait” por él, entra en un estado conocido como“zombie”. Su memoria se libera, no se planifica y su posible alarma se desactiva, sin embargo,todavía ocupa su entrada en la TP. Este estado no suele durar y cuando su padre, eventualmente,ejecuta “wait”, se produce la liberación de la entrada de la TP y se informa al GF y kernel para quehagan lo propio.Si un proceso muriese estando su padre ya muerto, habría un problema, porque un proceso“zombie” quedaría así para siempre. Para evitar esto, Minix hace que cuando un proceso muere,todos sus hijos, pasen a ser hijos de “Init”. Al arrancar el Sistema, “Init” lee el fichero “/etc/ttytab”para obtener la lista de todos los terminales, y hace “fork”, con cambio de imagen a “login”, porcada terminal. A continuación se bloquea a la espera de la terminación de cualquier proceso hijo yde este modo “limpiar” cualquier “zombie “huérfano.La llamada “exit” ejecuta el procedimiento “do_pm_exit”, el cual llama a “pm_exit” que es quien hacetodo el trabajo. Esto es porque a “pm_exit” también se le llama cuando un proceso termina por unaseñal, aunque con parámetros de llamada distintos.El procedimiento “pm_exit” hace lo siguiente: (1) Si el proceso tiene una alarma pendiente ladetiene. (2) Contabiliza al padre los tiempos consumidos por el proceso que acaba. (3) Notifica a laTS de que el proceso deja de ejecutarse. (4) Notifica al GF, y (5) a la TS después, del fin delproceso (exit) para que actualicen sus TP,s liberando las entradas del proceso respectivas. (6) Selibera la memoria del proceso. Para ello, primero se determina si el segmento de código está siendousado por algún otro proceso. Si no es así se libera, y a continuación se libera el segmento de datosy pila. (7) Si el proceso padre le está esperando (en un “wait”), se llama al procedimiento “cleanup”,el cual libera la entrada del proceso en la TP del GP, decrementa el contador de procesos ydespierta al padre. En caso contrario, deja al proceso en estado “zombie” y envía la señalSIGCHILD al padre. Después de “cleanup”, tanto si el proceso queda “zombie” como si no, serecorre la TP buscando cualquier proceso hijo. Si se encuentra alguno le hace hijo de ”Init”. Si “Init”está “WAITING” y algún hijo está “zombie” se llama al procedimiento “cleanup” para dicho hijo. 18
  • 19. Gestión de memoria Minix 3 4.4 Las llamadas al sistema, fork, exit y wait: (wait) Proceso de Usuario Esta respuesta se envía en cleanup. --do_waitpid-- ----SI ----- ----SI----- ▪Recorre la TP ----SI ----- return(0) ▪cleanup; y para cada ¿ Opción ---SI--- ▪return entrada: “WNOHANG” ? ¿ Está (SUSPEND) ¿ Es un proceso zombie ? hijo ? Gestor de Procesos estado=WAITING Return ¿ Está ¿ Tiene return(SUSPEND) (ECHILD) ----SI ----- algún hijo ? stopped ? return(pid) Significado de las flechas: send_rec (…) flechas send (…) Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 19 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.A la Izquierda, situación antes de quesalga el proceso 12.A la derecha un poco antes de salir.La función clean_up limpiaría elproceso zombie 53, y éste desapa-recería como hijo de init. El proceso52 seguiría adoptado por init.Cuando el proceso padre hace “wait” o “waitpid”, se ejecuta la función “do_waitpid”, la cual rastreala TP en busca de algún hijo. Si hay alguno, comprueba si está en estado “zombie”, en cuyo caso,se llama a la función “cleanup” y la función “do_waitpid” devuelve “SUSPEND”, como código deretorno (lo que significa que no se manda mensaje de respuesta al padre, sin embargo no quedarábloqueado porque la respuesta se envía en la función “cleanup”). Si se encuentra algún hijo enestado “stopped” (siendo trazado), se informa de ello en el mensaje de respuesta y se retorna (haymensaje respuesta al padre). Si no se hubiera encontrado ningún hijo en la TP, se devuelve error.Si hubiera hijos pero ninguno en estado “zombie” o “stopped”, dependiendo de si se ha llamado a“wait” con la opción de espera (caso normal) o no (WNOHANG), se deja al proceso bloqueado“WAITING” (se retorna SUSPEND y por tanto no se le responde con mensaje), o se retorna 0 (seresponde con mensaje y el proceso puede continuar).Cuando un proceso acaba y su padre lo estaba esperando, cualquiera que sea el orden de estoseventos, se llama al procedimiento “cleanup” para efectuar los últimos pasos. Queda poco porhacer. El padre es despertado de su “wait” y se le entrega el “pid” del hijo que ha finalizado, asícomo su código de salida (exit code). El GP ya ha liberado la memoria del proceso hijo y el kernelya ha suspendido la planificación y liberado su entrada en la TP, así como también el GF. En estepunto el proceso hijo se ha ido para siempre. 19
  • 20. Gestión de memoria Minix 3 4.5 La llamada al sistema execve (1/5) Al comprobar el tamaño requerido nunca se tiene en cuenta que la “C” hace execve() a liberación de la propia imagen un programa “D” de sumada a algún hueco contiguo 40 clics tamaño 70 clics. podría satisfacer el requisito de --------------------------- memoria. Si se puede compartir ¡ NO HAY MEMORIA ! C código sólo se pide memoria para 30 clics el segmento de datos+gap+pila. No se considera nunca la posibilidad de hacer dos peticiones de memo- 10 clics ria, aún siendo I+D separados. “B” hace execve() a un programa “E” I+D Juntos B con una pila de 20 clics Tamaños segmentos de “E” 1400 bytes ------------------------ -------------------- ¡ NO HAY MEMORIA ! Bytes Clics A Código 20.510 -- 60 clics Datos 220 BSS 10.000 31 20 clics Pila 1.400 2 d Total 32.740 32 MINIX Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 20 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Durante la llamada “execve”, cuando Minix busca un hueco de tamaño suficiente parasatisfacer una petición de memoria, no se tiene en cuenta si la memoria liberada por laimagen saliente sumada a algún posible hueco adyacente puede satisfacer dichapetición. Cuando el programa “C” hace “execve” sobre el programa “D”, Minix busca unhueco de tamaño suficiente para albergar a “D” al completo. Si “D” tiene espacios I+Dseparados, la necesidad podría repartirse en principio entre dos huecos, sin embargoMinix no solicita estos dos huecos, por lo que esto es algo mejorable. Sin embargoMinix, si contempla la posibilidad de que “D”, con I+D separados, pueda compartir elcódigo con algún programa ya en memoria, para buscar si es así, un único hueco parael segmento de datos+gap+pila.Cuando el programa “B” hace “execve” con una pila de 1.400 bytes, e intenta cambiar laimagen de memoria por la del programa “E” que tiene en su cabecera los tamañossiguientes: Text=20.510, Datos=220, BSS=10.000 y Total=32.740 con I+D juntos. Lallamada falla por memoria insuficiente. La explicación es la siguiente: El segmento dedatos incluye el código y datos no inicializados (BSS), su tamaño es 20.510 + 220 +10.000 = 30.730 que expresados en clics son 31. El tamaño total que son 32.740 bytesnos debería dejar un espacio para pila y gap de 32.740 – 30.730 = 2.010 bytes, que enprincipio sería suficiente para la pila de 1.400 bytes, sin embargo, en el mapa dememoria los segmentos se requieren en clics. El tamaño del segmento de pila son 2clics, y el tamaño “Total” en clics, según el campo del fichero es de 32 clics, que esinferior a la suma del de datos y pila (31+2). El programa “E” tendría que ser ejecutadocon un tamaño de pila máximo de 1 clic si se desea tener éxito en el “execve”. Esteproblema surge debido a la perdida de memoria que sufren los segmentos porfragmentación interna. 20
  • 21. Gestión de memoria Minix 3 4.5 La llamada al sistema execve (2/5) envp [ ] execve(“/bin/ls”, argv, envp) 0 t s A 8188 0 t s a 52 0 / r s u 8184 / r s u 48 0 t s A 8188 / = E M 8180 / = E M 44 / r s u 8184 O H 0 c 8176 HOME = /usr/ast O H 0 c 40 / = E M 8180 . g 0 c 8172 . g 0 c 36 O H 0 c 8176 - f 0 l 8168 - f 0 l 32 . g 0 c 8172 - 0 s l 8164 PILA - 0 s l 28 0 8160 - f 0 l 8168 0 24 - 0 s l 8164 8178 8156 42 20 0 8160 0 8152 0 16 8174 8148 argv [ ] 8178 8156 38 12 0 8152 8170 8144 0 34 8 8174 8148 8167 8140 g.c 31 4 8170 8144 8164 8136 f.c 28 0 8156 8132 8167 8140 envp -l 8136 8128 argv 8164 8136 DATOS ls crtso 4 8124 argc CODIGO return 8120 (a) (b) (c) Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 21 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.En la figura de arriba se muestran las operaciones básicas que se llevan a cabo con la piladurante la llamada “execve”, tomando como ejemplo la ejecución del comando “ls –l f.c g.c” enla “Shell”. Ésta interpreta dicho comando y efectúa la llamada: “execve (“/bin/ls”, argv, envp)”, lacual construye la pila inicial en el espacio de usuario tal y como se muestra en la figura de arriba(a), con direcciones relativas a la dirección virtual 0.Esta pila se copia tal cual a una variable local dentro del espacio del GP. Éste parchea la pilamodificando las direcciones de los punteros acorde a las direcciones que deberían tener, dentrode una pila ubicada en la nueva imagen. Suponiendo por ejemplo, que el tamaño de la memoriatotal del nuevo programa fuera de 8.192 bytes (la última dirección del programa sería la 8.191),entonces el GP, sabiendo que dicha pila se situará al final de la memoria disponible para elprograma, modificará las direcciones de todos los punteros dentro de la pila de acuerdo a sunueva ubicación y mandará a la TS que copie la pila, desde su copia local, a la nueva imagen enespacio de usuario.Con la llamada “execve” ya finalizada, la pila de la nueva imagen quedaría tal y como se muestraen la figura (b), con el puntero de pila en el valor 8.136. Todavía quedaría algo por resolver. Elprograma principal a ejecutar tendrá probablemente una función como esta: “main (argc, argv,envp)”. Para el compilador de “C” “main” es otra función más. El código compilado supone quelos tres parámetros, y la dirección de retorno están en la pila, y no es así como lo ha dejado“execve”. Por esto los programas no empiezan directamente en “main”. Hay una pequeña rutinallamada “C run-time, start-off” (crtso) que se monta (link) en la dirección de comienzo 0 y tomainicialmente el control. Su trabajo es apilar estos tres parámetros y llamar a “main” mediante“call”. El resultado de la pila se muestra en la figura (c ). Si desde “main” no se invocase “exit”para finalizar el programa, la dirección de retorno de la pila devolvería el control a la rutina crtso,la cual efectuaría la llamada a “exit” 21
  • 22. Gestión de memoria Minix 3 4.5 La llamada al sistema execve (3/5) - Si exceso en el tamaño de la pila o longitud ruta excesiva. ¡ Error execve ! - Obtiene el nombre del fichero. Lo copia de espacio de usuario a espacio del GP: sys_datacopy (). Si error ¡ Error execve! Envía SYS_VIRCOPY a la TS. - Copia la pila del proceso de espacio de usuario a espacio del GP: sys_datacopy (). Si error ¡ Error execve! Envía SYS_VIRCOPY a la TS. - Bucle de hasta dos iteraciones. Si es un “script” se ejecuta 2 veces. Si no sólo 1. ▪ Cambia al directorio de usuario: tell_fs (CHDIR,…); Envia CHDIR al GF. ▪ Comprueba si el fichero es ejecutable: fd=allowed (nombrefichero_ejecutable, …): access (). Envia ACCESS al GF. tell_fs (SETUID, superuser,..); Envía SETUID al GF. fd=open (). Envía OPEN al GF. tell_fs (SETUID, euid,..); Envia SETUID al GF. fstat (). Envía STAT al GF. Si fichero no ejecutable: close(fd); ¡ Error execve ! Si error envía CLOSE al GF. ▪ Lee la cabecera del fichero y obtiene los tamaños de los segmentos read_header (fd, &txt_bytes, &data_bytes, &bss_bytes, &tot_bytes, ….): read (fd, &header,..); Envía READ al GF. Comprueba tamaño mínimo de cabecera, número mágico, si es un script (“#!” dos primeros caracteres), etc. Si algo inválido se retorna error. Lee y establece espacios I+D juntos o separados. Prepara tamaños de los segmentos y comprueba si son coherentes. - Fin Bucle Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 22 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.La llamada “execve” está implementada por la función “do_exec()”. Después de efectuar algunascomprobaciones, el GP manda a la TS que copie el nombre del fichero ejecutable, desde elespacio de usuario al suyo propio. En el mensaje con la orden se incluye además la dirección ylongitud del nombre. A continuación vuelve a ordenar a la TS que copie la pila construida por lalibrería de usuario a una variable local propia. En el mensaje con la orden se incluye la direcciónde la pila y su tamaño. Seguidamente se entra en un bucle. Si el fichero es un binario el bucle seejecuta una única vez , si es un script dos. Primero veremos el caso de que fichero sea unbinario: 1) El GP envía un mensaje al GF para que cambie el directorio actual al directorio detrabajo del usuario. 2) Se llama a la función “allowed()” para comprobar si se permite la ejecución.Si es así, se abre el fichero y se devuelve el descriptor, sino se devuelve error y la llamada falla.3) Se lee la cabecera del fichero para obtener los tamaños de los segmentos. Si el fichero es unbinario el código devuelto provoca la salida del bucle.Lo que sucede si el fichero es un script es lo siguiente: Cuando se lee la cabecera del fichero secomprueban los dos primeros caracteres (#!) que indican que el fichero es un script, en la mismalínea también se especifica el programa que interpretará el script junto con posibles opciones, porejemplo: #! /usr/local/bin/perl wT. En este caso el fichero que se tiene que cargar en memoria esel binario intérprete del script en lugar del script, además se parchea la pila en la función“patch_stack()” añadiendo a ésta los parámetros indicados en la línea del script (respetando losque se hubieran especificado en la llamada “execve”).No se permite que el interprete de un “script” sea a su vez otro “script”, limitando el número deiteraciones del bucle a 2.Si hubiera algún error en la cabecera, se devolvería éste y la llamada “execve” fallaría. 22
  • 23. Gestión de memoria Minix 3 4.5 La llamada al sistema execve (4/5) - Si hubo algún error en cabecera: close (fd) ¡ Error execve ! Si error envía CLOSE al GF. - Comprueba si se puede compartir el segmento de código. - Toma memoria para la nueva imagen, libera la antigua, actualiza el mapa e informa al kernel. new_mem(): si error “alloc_mem()” ¡ Error execve ! si segmento código saliente no está siendo compartido “free_mem(seg_codigo,..)” “free_mem(seg_datos,..)” sys_newmap () Envía SYS_NEWMAP a la TS Rellena a 0’s BSS, gap y pila: sys_memset (…) Envia SYS_MEMSET a la TS - Parchea la pila y la copia desde el GP a la nueva imagen de memoria Parchea la pila : patch_ptr (..) Copia la pila: sys_datacopy (..) Envía SYS_VIRCOPY a la TS - Lee de disco el segmento de datos y posiblemente el de código a la nueva imagen de memoria Si código compartido se lo salta: lseek (fd,..) Posible envío LSEEK al GF sino, se leo del disco: rw_seg (R, fd, T,..) Posible envío READ(s) al GF Leo segmento datos: rw_seg (R, fd, D,..) Envío READ(s) al GF Cierra el fichero: close (fd) Envía CLOSE al GF Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 23 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.El siguiente paso es comprobar si se puede compartir el código. Para ello el GP se recorre la Tablade Procesos buscando un proceso cuyos campos “mp_ino, mp_dev y mp_ctime” indiquen que elfichero ejecutable es el mismo que el que se está intentando cargar en memoria, además de tenerespacios I+D separados. Si lo encuentra, guarda en una variable (“sh_pm”) esta situación (la cualrefleja I+D separados y código compartido).La función “new_mem()” comprueba si hay suficiente memoria para la nueva imagen. Si secomparte código (e I+D separados, “sh_pm”) se busca un hueco suficiente para el segmento dedatos y pila, sino el hueco ha de ser suficientemente grande para incluir además el código.Si la imagen entrante tuviera I+D separados pero no pudiera compartir código con ningún otroproceso, por ser dicho código el primero en entrar en memoria, sería factible y en principiodeseable, el solicitar dos huecos de memoria independientes para los dos segmentos del proceso.Esto supondría una mejora sobre la implementación de Minix ya que actualmente no lo hace así.Si hubo suficiente memoria (éxito en alloc_mem) se libera la memoria de la imagen saliente (no seliberaría el segmento de código si este estuviera siendo compartido por algún otro proceso) y seasigna memoria para la imagen entrante. Se actualiza el mapa de memoria (campo “mp_seg”) y seinforma al kernel con “sys_newmap()”. Finalmente “new_mem()” encarga a la TS la inicialización a0’s las áreas bss, gap y pila mediante la llamada al kernel “sys_memset()”.A continuación se parchean las direcciones de los punteros en la pila tal y como ya se ha vistomediante el procedimiento “patch_ptr()” y se manda a la TS que copie la pila parcheada, desde elespacio del GP al espacio de usuario de la nueva imagen, con la función “sys_datacopy()”.Finalmente, se leen y se llevan los segmentos de código y datos de disco a memoria (el segmentode código sólo se lee y lleva si el código no es compartido [variable “sh_pm”]). 23
  • 24. Gestión de memoria Minix 3 4.5 La llamada al sistema execve (5/5) - Comprueba y maneja los bits “setuid” y “setgid” Si el bit SET_UID del fichero está activo: usr_efectivo proceso = uid del fichero: tell_fs (SETUID,..); Envía SETUID al GF Si el bit SET_GID del fichero está activo: grupo_efectivo proceso = gid del fichero: tell_fs (SETGID,..); Envía SETGID al GF - Actualiza adecuadamente los campos de la entrada de la TP del proceso Resetea las señales capturadas. Tratamiento a SIG_DFL. Desenmascara todas las señales. Establece flag de I+D acorde con el del fichero. Informa al GF de execve: tell_fs (EXEC,..); Envía EXEC al GF Establece el campo “mp_name” al nombre del fichero ejecutado (para depuracion, ps, salida , etc.) - Informa al kernel de que el proceso es ejecutable sys_exec (who, new_sp, name, pc); Envía SYS_EXEC a la TS - Causa la señal SIGTRAP si el proceso estuviese siendo trazado. if (TRACED) check_sig (rmp->mp_pid, SIGTRAP); - No se responde: return (SUSPEND); Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 24 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.La función “rw_seg()” en vez de leer y copiar a espacio de usuario el fichero bloque a bloque,utiliza un truco para permitir al GF cargar de una sola vez el segmento al espacio de usuario. Lallamada es decodificada por el GF de una forma ligeramente especial. Hace parecer que lalectura es de todo el segmento por parte del proceso de usuario mismo. Sólo unas pocas líneasdel comienzo de la rutina de lectura del GF son precisas para tratar este aspecto “extraño”. Conesto se consigue una apreciable incremento en la velocidad de carga del(de los) segmento(s) .Por último señalar, que si la llamada ha tenido éxito no se puede responder al proceso que lainvocó. La forma en que el proceso reanuda la ejecución es atípica, no es como respuesta a laprimitiva “send_rec()” que se empleó en la llamada, sino que la TS al recibir el mensajeSYS_EXEC se encarga de retirar al proceso de la cola de procesos que esperan recibir unmensaje y ponerlo en la cola de planificación, con el contador de programa inicializado a laprimera instrucción del programa. 24
  • 25. Gestión de memoria Minix 3 4.6 La llamada al Sistema brk Proceso de Usuario Posible respuesta ▪Restaura los antiguos con error o no de- valores de los segmentos pendiendo de la ▪Responde error comprobación anterior ▪¿ Caben los segmentos de datos y pila en el Responde espacio de usuario ? OK Gestor de Procesos ▪Comprueba que el nuevo ------- adjust ------- valor es distinto del SYS_GETINFO ▪Comprueba si el tamaño de SYS_NEWMAP anterior y si lo es, que la pila quedaría negativo. ----SI --- no es inferior al comienzo ▪Calcula el tamaño del gap. Informa a la TS del segmento de datos. ▪Añade un margen de segu- del nuevo mapa ▪Pide a la TS el valor del ridad para crecimiento pila. de memoria puntero de pila ▪Actualiza tamaño segmento Tarea del de datos y tamaño y origen del segmento de pila. Sistema ▪Devuelve entre otras cosas el puntero de pila Significado de las flechas: send_rec (…) flechas send (…) Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 25 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Los procedimientos de librería “brk y sbrk” se utilizan para ajustar el límite superior del segmentode datos. El primero tiene como parámetro la dirección del límite superior del segmento de datosy la segunda un incremento o decremento del tamaño actual del segmento de datos. Esta últimaen realidad lo único que hace es calcular el nuevo tamaño del segmento de datos y llamar a “brk”.El modelo básico de memoria de Minix es bastante simple, se asigna un espacio contiguo dememoria para los segmentos de datos y pila al crearse el proceso. Este espacio (segmento intel)no puede reubicarse, crecer, ni disminuir. Lo único posible es que el segmento de datos aumentesu límite superior a costa del gap desde abajo, o que el segmento de pila crezca hacia abajo acosta del gap por arriba. Con estas limitaciones la implementación es sencilla. Consiste encomprobar que los cambios encajan en el espacio de direcciones, ajustar las tablas e informar al“kernel”.La parte principal de esta llamada la hace el procedimiento “adjust”, el cual comprueba que lossegmentos de datos y pila no colisionen. Si lo hicieran la llamada fallaría. Al hacer estacomprobación se añade al segmento de datos unos bytes de margen de seguridad(SAFETY_BYTES), tal que la decisión de que la pila ha crecido mucho pueda hacerse contodavía suficiente espacio en la pila (margen de seguridad).La base del segmento de datos es constante, por tanto sólo se ajusta su tamaño. La pila crecehacia abajo, si “adjust” descubre que el puntero de pila se ha situado más abajo del origen delsegmento de pila, entonces se cambia tanto el origen como el tamaño. 25
  • 26. Gestión de memoria Minix 3 4.7 Tratamiento de señales Las tres fases del tratamiento con señales: Preparación: El código del programa se prepara para una posible señal. Respuesta: La señal se recibe y se toma un acción. Restauración: Se restaura la operación normal del proceso. La estructura “sigaction”: struct sigaction { __sighandler_t sa_handler; /* SIG_DFL, SIG_IGN, SIG_MESS, o puntero a función */ sigset_t sa_mask; /* señales a bloquear durante el manejador */ int sa_flags; /* flags especiales */ } Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 26 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Las señales constituyen una forma de enviar información a un proceso que no la está esperando.Existe un conjunto definido de señales. Cada señal tiene una acción por defecto, bien matar alproceso que la recibe o bien ser ignorada, sin embargo, los procesos puede usar llamadas alSistema para alterar estas acciones. Un proceso puede hacer que una señal sea ignorada o bienhacer que se ejecute un tratamiento cuando se reciba, exceptuando en ambos casos la señalespecial “kill”. Así, para el programador hay dos momentos distintos en el que el S.O. trata conlas señales. Una fase de preparación, en la que un proceso modifica la respuesta a una futuraseñal, y una fase de respuesta, en la que la señal es generada y se actúa en consecuencia. Laacción puede ser la ejecución de un manejador de señal personalizado. Existe una tercera fase.Cuando el manejador acaba, una llamada al Sistema especial restaura la operación normal delproceso “señalado”. El programador no necesita saber de esta fase. El escribe el tratamiento deseñal como una función más. El S.O. se ocupa de los detalles de invocar y terminar el manejadory gestionar la pila.Hay varias llamadas al Sistema que en la fase de preparación puede modificar la acción pordefecto de una señal. La más general es “sigaction()” que puede especificar que se ignore,capture (especificando una función manejadora) o restaure la acción por defecto de una señal.Otra llamada, “sigprocmask()”, puede bloquear una señal, haciendo que se encole y que actúesólo cuando el proceso la desbloquee, en un momento posterior. La fase de preparación se hacedesde el GP. Cada proceso tiene varios “bitmaps”, uno de ellos define las señales a serignoradas, otro las capturadas, etc. También dispone de una tabla de estructuras “sigaction”, detantos elementos como posibles señales. Con este campo se puede saber para cada señal lafunción de tratamiento (“sa_handler”), las señales bloqueadas durante la ejecución deltratamiento (“sa_mask”). El valor de “sa_handler” además del de la dirección de una funciónpuede ser SIG_DFL (tratamiento por defecto) y SIG_IGN (ignorar). Los procesos del Sistemausan el nuevo tipo de manejador “SIG_MESS”, que le dice al GP que redirija una señal medianteun mensaje de notificación SYS_SIG. No se requiere la fase tres de restauración para las señalestipo SYG_MESS. 26
  • 27. Gestión de memoria Minix 3 4.7 Tratamiento de señales Señal Descripción Generada por SIGHUP “Hangup” Llamada al Sistema kill SIGINT Interrupción TTY SIGQUIT Abandonar (Quit) TTY SIGILL Instrución ilegal Kernel (*) SIGTRAP “Trace trap” Kernel (M) SIGABRT Terminación anormal TTY SIGFPE Excepción punto flotante Kernel (*) SIGKILL “kill” (no puede ser capturada ni ignorada) Llamada al Sistema kill SIGSEGV Violación de segmento Kernel (*) SIGPIPE Escritura en un pipe sin nadie para leerlo Gestor de Ficheros SIGALRM Alarma vencida Gestor de Procesos SIGTERM Terminación por software, kill() Llamada al Sistema kill SIGCHILD Proceso hijo finalizado o detenido Gestor de Procesos SIGKMESS Mensaje del Kernel Kernel SIGKSIG Señal pendiente del Kernel Kernel SIGKSTOP Kernel apagando (shutting down) Kernel (*) Dependientes del Hardware. (M) De Minix, no de Posix. Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 27 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Cuando se genera una señal intervienen varias partes de Minix. La respuesta empieza en el GP, elcual sabe qué procesos deben recibir la señal gracias a las estructuras ya mencionadas. Si la señalestuviera capturada, el GP se la envía al proceso destinatario. Esto requiere salvar el estado delproceso (para que pueda continuar su ejecución donde se quedó). Esta información la salva en lapila del proceso “señalado”, comprobando previamente si hay espacio en ella, y encargándoselo ala TS. La TS, además, manipula el contador de programa para que apunte al comienzo delmanejador de la señal. Cuando el manejador acaba se efectúa una llamada al sistema “sigreturn”.Mediante esta llamada, el GP y el “kernel” participan en la restauración del contexto del proceso“señalado” para que pueda retornar a su ejecución. Si la señal no estuviera capturada se ejecuta laacción por defecto. El GP puede tener que repetir más de una vez estas acciones, ya que una señalpuede tener que ser distribuida a un grupo de procesos.Minix define todas las señales obligatorias de Pósix estándar, aunque no todas las opcionales.Tradicionalmente las señales pueden generarse de dos modos: por la llamada al Sistema “kill”, ypor el “kernel”. Las señales “sigint y sigquit” pueden originarse por la pulsación de teclas especialesdel teclado. “sigalrm” es manejada por el GP. “sigpipe” por el GF. El programa “kill” puede enviarcualquier señal a cualquier proceso. Algunas señales dependen del hardware, por ejemplo el 8086no soporta la detección de “instrucción ilegal”.Con independencia del origen de la señal, el GP procesa todas las señales del mismo modo. Paracada proceso a ser “señalado” se efectúa una serie de comprobaciones. Un proceso puede enviaruna señal a otro si es el superusuario, o si su usuario real o efectivo es igual al usuario real oefectivo del destinatario. Algunas condiciones impiden el envío. a) El destinatario no puede ser“zombie”, b) la señal no debe estar ignorada ni bloqueada (no es lo mismo estar bloqueada queignorada, las señales bloqueadas se envían si/cuando finaliza la situación de bloqueo), y por últimoc) si el espacio de pila es insuficiente, el proceso “señalado” es eliminado (“killed”).Si se cumplen todas las condiciones, la señal se envía. Si la señal no está capturada no se envíainformación al proceso. En ese caso el GP mata al proceso (o ignora la señal si esa fuera su acciónpor defecto). Algunas señales no están soportadas en Minix, pero si definidas aunque ignoradas, taly como permite el estándar Posix. Estas son: SIGUSR1, SIGUSR2, SIGCONT, SIGSTOP, SIGSTP,SIGTTIN y SIGTTOU. 27
  • 28. Gestión de memoria Minix 3 4.7 Tratamiento de señales Dir. Retorno Dir. Retorno Dir. Retorno Dir. Retorno Vars. locales Vars. locales Vars. locales Vars. locales del proceso del proceso del proceso del proceso Regs CPU Regs. CPU originales Originales Pila Dir Ret 2 Dir. Ret 2 Estructura Vars. Locales Sigframe Sigreturn Dir. Ret 1 Vars. Locales Manejador Tabla Procesos Marco de pila Registros Regs. CPU Regs. CPU Registros CPU modificados Modificados CPU (originales) CP=manejador CP=manejador originales Antes Manejador eje- Sigreturn eje- Vuelta a normal (a) cutandose (b) cutandose (c) (d) Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 28 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.Capturar una señal significa ejecutar una función de tratamiento personalizada para dicha señal(manejador de la señal). La dirección de este manejador está guardada en la estructura“sigaction” de la Tabla de Procesos (TP). Modificando el marco de pila (“stackframe” guardado enla TP) de un proceso “señalado” se consigue que la próxima vez que se le permita ejecutar, seejecute el manejador. Modificando la pila del proceso, se consigue que cuando el manejadoracabe, se ejecute la llamada al Sistema “sigreturn” . Esta llamada no la programa el usuario; seejecuta después de que el “kernel” haya puesto su dirección en la pila, de tal modo que sea éstala dirección de retorno que se saca de la pila cuando termina el manejador. “Sigreturn” restaura el“stackframe” original del proceso “señalado”, para que éste pueda volver a ejecutarse desde elpunto donde fue interrumpido por la señal.En (a) se muestra una vista simplificada de la pila y parte de su descriptor de proceso, justodespués de haber sido expulsado por una interrupción. En el momento de la expulsión losregistros de la CPU se copian a la estructura “stackframe” de la TP del kernel del procesoexpulsado. Esta sería la situación en el momento en que la señal es generada. Las señales songeneradas por un proceso diferente al destinatario, por ello este último no puede estarejecutándose en ese momento. En la preparación del manejo de la señal, la TS copia el“stackframe” de su TP en la pila del receptor como una estructura “sigcontext”, preser-vandola,después se apila una estructura “sigframe”, con información que usará “sigreturn” cuando acabeel manejador. También apila la dirección Ret1 de la función que ejecutará a la propia “sigreturn” yotra dirección de retorno, Ret2, que es donde debe volver el programa interrumpido, aunque estaúltima no se usa en la ejecución normal. El contador de programa (CP) del “stackframe” de la TPse modifica para hacer que sea el manejador el que se ejecute cuando el proceso “señalado”vuelva a ejecución. En (b) se muestra la situación después de la preparación y con el manejadorejecutándose. (C) muestra la situación con “sigreturn” ejecutándose. El resto de la estructura“sigframe” ahora son sus variables locales. “Sigreturn” acaba como cualquier otra llamada alSistema, permitiendo que el planificador seleccione el siguiente proceso. Eventualmente elproceso “señalado” será planificado y retomará el control a partir de esta dirección (Ret2). Lamisión de “sigreturn” es dejar las cosas como estaban. El “stackframe” de la TP es restaurado asu estado original, usando la copia de la pila. (d) muestra la situación final, con el procesoesperando volver a su ejecución en el punto o estado en el que estaba cuando se interrumpió. 28
  • 29. Gestión de memoria Minix 3 4.7 Tratamiento de señales. sigaction (int sig, const struct sigaction *act, struc sigaction *oact) int do_sigaction() { Proceso de Usuario Si (sig = SIGKILL) return (OK) Si (sig <1 o sig > NSIG) return (EINVAL) Si (oact != NULL) Pide a la TS que copie la estructura “sigaction” de la send_rec: SIGACTION TP a “oact” ….. sys_datacopy (…). Si (act = NULL) return (OK) Pide a la TS que copie de “act” a la estructura “sigaction” Gestor de Procesos de la TP .….. sys_datacopy (…). Si (act->sa_handler = SIG_IGN) sigaddset (mp_ignore) send_rec: SYS_VIRCOPY sigdelset (mp_sigpending, mp_catch, mp_sig2mess) Una o dos veces sino si (act->sa_handler = SIG_DFL) sigdelset (mp_ignore, mp_catch, mp_sig2mess) sino si act->sa_handler= SIG_MESS) Tarea del Sistema si (! (mp_flags & PRIV_PROC)) return (EPERM) sigaddset (mp_catch..) sigdelset (mp_ignore, mp_sig2mess) sino sigaddset (mp_catch) sigdelset (mP-ignore, mp_sig2mess) } Aníbal Ramírez García - Sistemas Operativos II - Departamento de Informática Aplicada - Capítulo IV. Pag. nº 29 Escuela Universitaria de Informática - Universidad Politécnica de Madrid.La llamada “sigaction” soporta ambas funciones: sigaction() y signal(), las cuales le permiten a unproceso alterar su respuesta a las señales. “Sigaction()” es la requerida por POSIX y en general se laprefiere para la mayoría de los propósitos, aunque “signal()” es “C” estándar y se necesita paraportabilidad con sistemas NO-POSIX. El código comienza con una validación: Que el número de señalsea válido y que no se intente alterar la respuesta a la señal “sigkill”. A continuación se invoca a la tareade sistema para que copie los atributos a la estructura “oact”, si el puntero a ésta no fuera NULL, ademássi el puntero a “act” no fuera NULL, se coparian los atributos de esta estructura al espacio del GP. Másadelante se modifican los mapas de bits mp_catch, mp_ignore y mp_sigpending, de acuerdo a la que lanueva acción sea ignorar, capturar o restaurar el tratamiento por defecto de la señal. El campo“sa_handler” de la estructura “sigaction” contiene el puntero a la función que se ejecutará si señal escapturada, o bien alguno de los valores especiales SIG_IGN o SIG_DFL, definidos en POSIX. Tambiénes posible el valor SIG_MESS que es especifico de Minix. Se utiliza para procesos del sistema. Estosprocesos están normalmente bloqueados a la espera de un mensaje, de este modo, el método normalpor el cual el GP le pide al kernel que ponga un marco de señal en la pila del receptor, será demoradohasta que un mensaje despierte al receptor. El código SIG_MESS le dice al GP que emita un mensaje denotificación, el cual es prioritario sobre un mensaje normal. Este mensaje de notificación contiene comoargumento un conjunto de señales pendientes, permitiendose con ello que se pasen multiples señales enun solo mensaje.Finalmente, los otros campos de la TP del GP relacionados con señales son rellenados. Para cadaposible señal hay un “bitmap”, sa_mask, en el que se definen que señales deben bloquearse mientras elmanejador de esa señal se esté ejecutando. También hay para cada señal un puntero, sa_handler. Éstepuede contener la dirección de una función de tratamiento, o valores especiales para indicar si la señalserá ignorada, tendrá tratamiento por defecto oo se será usada para generar un mensaje. La direcciónde la rutina de librería que invoca sigreturn cuando termina el manejador es almacenada enmp_sigreturn. Esta durección es uno de los campos del mensaje recivido por el GP. 29