Ingeniería Informática. Curso 3º Sistemas Operativos Examen Final. PROBLEMAS. 5 de Septiembre de 2008 1. Es necesario modelar el comportamiento de un ascensor que presta servicio a un edificio de 20 pisos. Dicho ascensor es utilizado por robots para subir a su planta destino. El ascensor se encuentra inicialmente en la planta baja. Los robots afluyen continuamente y van accediendo al ascensor en la planta baja. Cuando hay 5 robots en el ascensor, éste cierra sus puertas; los demás robots tendrán que esperar. Cada robot que consigue acceder al ascensor solicita un piso de destino (por simplicidad consideraremos que cada robot subido al ascensor va un piso diferente). Una vez ocupado el ascensor al completo, éste se pone en marcha y sube, accediendo a los pisos solicitados en orden de recorrido. El robot que haya llegado a su destino se baja y acaba su operación. Vaciado el ascensor, éste regresa inmediatamente a la planta baja para cargar 5 nuevos robots. El comportamiento de ambos procesos los podemos esquematizar así: robot(int piso_destino) - Esperar a que haya sitio en el ascensor, y entrar cuando sea posible; - Pulsar piso de destino; - Notificar al ascensor si ya hay 5 robots - Esperar a que el ascensor alcanza el piso destino; - Bajar ascensor() Ir a planta baja(); // función dada. No implementar while (true) { esperar a que entren 5 robots; for (i=0; i<5; i++) { - determinar siguiente piso destino - avisar al robot adecuado; } Ir a planta baja() } (a) (2 puntos) Codificar los procesos robot() y ascensor() empleando cerrojos y variables condicionales con los siguientes significados: A: variable de condición para la espera de los robots a la entrada del ascensor. B: variable de condición para la espera del ascensor en la planta baja. C: variable de condición para notificar la bajada de un robot en su planta destino. PISOS[20]: array de variables de condición para la espera de un robot dentro del ascensor hasta llegar a su destino. La pulsación del piso de destino se simula mediante la puesta a TRUE de la entrada correspondiente de un array PISOS_pulsados[20], inicializado a FALSE. (b) (3 puntos) Codificar el mismo problema utilizando ahora el mecanismos de sincronización de semáforos generales para que tengan el siguiente comportamiento. Determina en primer lugar las variables y semáforo que consideres necesarios, indicando claramente el valor inicial de cada uno. 2. Dado el código que se presenta a continuación, y asumiendo que el directorio data existe y contiene inicialmente un fichero llamado result, responde a las siguientes preguntas: a. b. c. (1 punto) Dibujar el estado de las tablas de descriptores de ficheros (tdda), intermedia (TIN) y de nodos-v (I-nodos) justo antes de la finalización del proceso hijo. Asuma que el proceso padre es más prioritario que el hijo. (2 puntos) Si el sistema de ficheros es tipo FAT, indica un posible estado final del sistema, incluyendo tanto las entradas de la FAT como los bloques de datos relevantes (incluyendo los directorios data y doc). Los bloques de datos son de 1KB (1024 bytes). (2 puntos). Asumir ahora que el sistema de ficheros usado es una simplificación del modelo de Unix: nodos-i con 4 punteros directos y uno indirecto. Indica el contenido de los nodos-i y de los bloques de datos relevantes (incluyendo los directorios data y doc). Los bloques de datos son de 1KB (1024 bytes). int fd1; int fd2; char buf1[2000]=”aaaa...a”; char buf2[1500]=”bbbb...b”; void hijo( ) { fd2=open(”data/result”,O_RDWR); write(fd1,buf1,2000); lseek(fd1,2500,SEEK_CUR); write(fd1,buf1,500); write(fd2,buf2,1500); close(fd2); } main() { mkdir(”data/doc”); //Creación de dir doc fd1=open(“data/doc/examen”,O_CREATE…); if (fork() == 0) { hijo(); exit(0); } else { //Escribimos 1500 c’s en buf2 memcpy(buf2,”cccc...c”,1500); fd2=open(”data/result”,O_RDWR); wait(NULL); lseek(fd1,1500,SEEK_CUR); write(fd1,buf2,500); write(fd2,buf2,500); } } Ingeniería Informática. Curso 3º. Sistemas Operativos Examen Final. TEORIA. 5 de Septiembre de 2008 1. [PROCESOS] a) Considerar el siguiente grafo de precedencia de procesos/procedimientos: C E G A B D F Proponer el código del esquema de ejecución de este grafo (1)usando fork() y wait(). b) Indicar al menos 5 causas por las que el kernel de un sistema operativo se vea obligado a hacer entrar en operación al planificador de procesos, si este utiliza una política de planificación expropiativa por prioridades similar a la de Linux. 2. [SINCRONIZACION Y COMUNICACIÓN] a) La existencia de una instrucción test-and-set en el repertorio de instrucciones del procesador permite incorporar al kernel del sistema operativo funciones básicas de sincronización lock y unlock del tipo llamado con “espera activa”. Dos posibles implementaciones alternativas a la estudiada de la operación lock() son las siguientes VERSION 1 while (test-and-set(cerrojo)) yield(); // ceder uso de CPU VERSION 2 while (TRUE) { if (!test-and-set(cerrojo) break; while (cerrojo == 1) ; } ¿Qué ventajas respecto a la implementación básica original aportan cada una de las dos versiones? Recuerda la implementación básica: while (test-and-set(cerrojo)) { } b) Considerar los siguientes mecanismos de sincronización: mutex, variables condicionales, semáforos anónimos, semáforos con nombre. Y los siguientes mecanismos de comunicación: memoria compartida, pipes anónimos, pipes con nombre, paso de mensajes. Indicar cuáles serán los mecanismos preferiblemente aplicables y por qué para cada uno de los siguientes escenarios: (1) coordinación entre threads, (2) coordinación entre procesos emparentados (por ejemplo, entre padre e hijo) o (3) coordinación entre procesos no emparentados. 3. [MEMORIA] a) ¿Qué relación hay entre un fichero ejecutable y el mapa de memoria de un proceso? ¿Cómo contribuye al mapa de memoria de proceso una biblioteca estática? ¿Y una biblioteca dinámica? b) Describir la operación de tratamiento de un fallo de página en caso de gestión de memoria virtual paginada por demanda con política de reemplazamiento por buffering. c) El espacio virtual de memoria de un proceso es la suma de los espacios virtuales de los hilos que lo integran. ¿Cierto o falso? Razonar. 4. [ENTRADA/SALIDA] a) En relación al dispositivo reloj, indicar qué afirmaciones son ciertas. Justifica tu respuesta- Siempre que se produce una oscilación del reloj se produce una interrupción del mismo. - El tiempo entre dos interrupciones de reloj es configurable por el sistema operativo. - Una de las funciones típicas gestionadas por el reloj es la planificación de procesos b) Señala, de entre las siguientes, las ventajas que aporta la utilización de los buffers del sistema operativo en dispositivos de bloques. Justifica tu respuesta. - Mejora del rendimiento en grandes accesos secuenciales. - Mejora el rendimiento al no tener que acudir siempre al dispositivo para realizar la operación requerida - Permite el uso simultáneo de dispositivos de uso exclusivo. c) Comparar las modalidades RAID4 y RAID5, indicando cuál es la usada habitualmente y por qué. Si disponemos de un RAID5 con cuatro discos, ¿cuántos discos se leen/modifican por una escritura de un bloque? 5. [SISTEMA DE FICHEROS] a) Enumera los distintos tipos de ficheros que admite típicamente un sistema de ficheros UNIX e indica si la llamada lseek() le es aplicable o no. ¿Qué explicación tiene en cada caso la situación EOF – Fin de Fichero? b) ¿Qué beneficio y/o perjuicio tendría que la primer parte (por ejemplo, los primeros 512 bytes) de un fichero UNIX se almacenase en el mismo bloque de disco que su i-nodo?. En caso de ser así, ¿cuántas operaciones de disco se necesitarían como mínimo para obtener el i-nodo del fichero /home/pepe/practica2/prog.c suponiendo que en memoria ya se encuentra el i-nodo del directorio raíz, pero ninguna otra cosa de las necesarias para recorrer la ruta? SOLUCIONES DEL EXAMEN DE SSOO. SEPTIEMBRE 2008. PROBLEMA 1 Solución con variables condicionales Declaraciones iniciales condvar A; espera de robots para subir al ascensor condvar B; espera de ascensor a que suban 5 robots en planta baja int ocupados=0; contador de robots dentro del ascensor condvar PISOSA[20]; array de 20 condiciones una por cada piso boolean PISOSB[20]; array de 20 booleanos con el estado de piso-solicitado – inicial a FALSE condvar C=0; notificación de bajada de robot del ascensor mutex mutex; Proceso robot(int destino) Proceso ascensor() lock(mutex); while (ocupados >=5) waitc(A,mutex); ocupados++; PISOSB[destino] = TRUE; if (ocupados==5) signalc(B); waitc(PISOSA[destino], mutex); ocupados--; PISOSB[destino] = FALSE; signalc(C); unlock(mutex); while (TRUE) { lock(mutex); while (ocupados < 5) waitc(B, mutex); p=0; for (i==0; i<5; i++) { while(PISOSB[p]==FALSE) p++; signalc(PISOSA[p]); waitc(C, mutex); } unlock(mutex); Ir_a_planta_baja; broadacast(A); } Solución con semáforos Declaraciones iniciales Semáforo A=5; espera de robots para subir al ascensor Semáforo B=0; espera de ascensor a que suban 5 robots en planta baja int ocupados=0; contador de robots dentro del ascensor semáforo PISOSA[20]; array de 20 semáforos uno por cada piso, iniciados a 0 boolean PISOSB[20]; array de 20 booleanos con el estado de piso-solicitado – inicial a FALSE Semáforo C=0; notificación de bajada de robot del ascensor Semáforo mutex; Proceso robot(int destino) Proceso ascensor() wait(A); wait(mutex); ocupados++; if (ocupados==5) signal(B); PISOSB[destino] = TRUE; signal(mutex); wait(PISOSA[destino]); wait(mutex); ocupados--; PISOSB[destino] = FALSE; signal(mutex); signal(C); while (TRUE) { wait(B); p=0; for (i==0; i<5; i++) { wait(mutex); while(PISOSB[p]==FALSE) p++; signal(mutex); signal(PISOSA[p]); wait(C); } Ir_a_planta_baja; for (i==0; i<5; i++) signal(A); } PROBLEMA 2. Estado de las tablas justo ANTES de la llamada close(fd2) del proceso hijo: Tdaa Padre Entrada estándar Salida estándar Salida error (fd1) ->id1 de TIN (fd2) -> id2 de TIN Tdaa hijo Entrada estándar Salida estándar Salida error (fd1) -> id1 de TIN (fd2) -> id3 de TIN TIN (tabla global) Entrada Id1: Id2: Id3: N punteros 2 1 1 Contador 5000 0 1500 Permisos R,W R,W R,W Puntero a nod-v Visión LÓGICA del estado final de cada fichero: Examen -> 2000 ‘a’ (BL 0 -1) – blancos hasta 4500 (BL 1,2,3y4) – 500 ‘a’ (BL 4) – blancos hasta 6500 (BL 4, 5 y 6) – 500 ‘c’ (BL6). Total 7 bloques lógicos Result -> 500 ‘c’ (BL 0) – 1000 ‘b’ (BL 0 y 1). Total 2 bloques lógicos b) Sistema FAT. Posible FAT: 0 eof 1 eof 2 3 3 eof 4 5 5 6 6 7 7 8 8 9 9 10 10 eof 11 free 12 free El bloque FÍSICO 0 contendrá las entradas del directorio “data”: Nombre fichero Doc Result Tipo D R Tamaño Fecha Permisos….. Primer bloque Físico --……… 1 1500 ………………… 2 El bloque FÍSICO 1 contendrá las entradas del directorio “data” : Nombre fichero examen Tipo R Tamaño Fecha Permisos….. 7000 ………………… 4 El fichero “result” se almacenará en los bloques físicos 2 y 3. El fichero “examen” ocupará los ficheros físicos 4,5,6,7,8,9 y 10 (si bien, los bloques 6, 7 y 9 contendrán únicamente espacios en blanco). c) Sistema tipo Unix Necesitaremos 4 nodos-i: Nodo-i 3 (relativo al directorio /data) Tipo: D P. Dir 0: 33 P. Dir 1: NULL P. Dir 2: NULL P. Dir 3: NULL P. Ind. : NULL Nodo-i 8 (relativo al fichero /data/result) Tipo: R …. P. Dir 0: 15 P. Dir 1: 16 P. Dir 2: NULL P. Dir 3: NULL P. Ind. : NULL Nodo-i 7 (relativo al directorio /data/doc) Tipo: D P. Dir 0: 12 P. Dir 1: NULL P. Dir 2: NULL P. Dir 3: NULL P. Ind. : NULL Nodo-i 12 (relativo al fich. /data/doc/examen) Tipo: R P. Dir 0: 40 P. Dir 1: 41 P. Dir 2: NULL P. Dir 3: NULL P. Ind. : 42 Bloques (físicos) de datos ocupados: Bloque 33 (entradas de /data) . 3 .. ? doc 7 result 8 Bloque 12 (entradas de …/doc) . 7 .. 3 examen 12 Bloques físicos 15 y 16: contenido de /data/results Bloques físicos 40 y 41: contenido de los bloques lógicos 0 y 1 de /data/doc/examen Bloque físico 42 (bloque físico dedicado a albergar punteros a otros bloques físicos) 43 NULL 47 NULL NULL ……. Bloque físico 43: contenido del bloque lógico 4 de …/examen Bloque físico 47: contenido del bloque lógico 6 de …/examen TEORIA Cuestión1 a) Con fork() y wait() pidA = Fork(); exec(“A); wait(pidA); pidB = fork(); exec(“B”); pidC = fork(); exec(“C”); wait(pidC); pidE = fork(); exec(“E”); wait(pidB); pidD = fork() ; exec(“D”) ; wait(pidE); wait(pidD); pidF = fork() ; exec(“F”); wait(pidF); pidG = fork(); exec(“G”); wait(pidG); b) Puntos de activación del planificador 1. Acaba el proceso en ejecución P 2. P realiza una llamada bloqueante (p.ej, pause()) 3. P causa una excepción que lo bloquea (p.ej., fallo de página mayor) 4. P desbloquea un proceso más prioritario (p.ej., signal(sem) o msgsend(q,m)) 5. Una interrupción desbloquea un proceso más prioritario que P. (p.ej., fin de temporizador, o de operación de disco o de operación de Terminal) 6. Una interrupción de reloj marca el fin del quanto de P 7. P cede el uso de la CPU: yield(); 8. P hace una llamada que rebaja su prioridad y como consecuencia otro proceso resulta más prioritario (p.ej., nice(10)) 9. P crea un hilo más prioritario (p.ej. pthread_create()) Cuestión 2. a) Ventaja VERSION 1: reduce la espera activa al permitir que otros procesos preparados para ejecutarse tengan la posibilidad de ser planificados mientras dure la espera activa por el cerrojo Ventaja VERSION 2: la operación test-and-set supone un doble acceso indivisible a la dirección de memoria del “cerrojo” – una para leer su contenido y otra para escribir (un 1) en él. Con esta versión, mientras la espera activa detecte que el valor del cerrojo es 1 solo realizará operaciones de lectura de memoria, ahorrando así los ciclos de escritura. b) Sincronización Comunicación Threads Procesos emparentados Procesos no emparentados Mutex, varcond Memoria_compartida Semáforos_anónimos Pipes anónimos, Memoria compartida Semáforos con nombre Pipes con nombre Memoria compartida Paso de mensajes Cuestión 3. a) El fichero ejecutable tiene una estructura fija en la que se incluyen secciones (código, datos con valor inicial) que se convertirán en regiones de memoria. En el fichero existe una Tabla de Secciones que marca el comienzo y tamaño de cada sección dentro del fichero. Una biblioteca estática ya está incluída en el fichero ejecutable, por tanto no modifica el mapa de memoria durante la ejecución del proceso (formará parte de la región de código y de la región de datos) Sin embargo, en el caso de una biblioteca dinámica, el código necesario se incluirá en el mapa de memoria del proceso cuando éste haga uso de una función de la biblioteca o durante la carga del programa (creándose nuevas regiones de forma dinámica). b) Fallo de página -> excepción -> (asumiendo dirección de usuario) el S.O. comprueba la dirección virtual para saber si está en una región válida del mapa del proceso (podría ser una expansión de pila) -> Buscar en la(s) listas asociadas al buffering si el contenido aún reside en memoria (fallo menor). Si es así, no hay que buscar marco libre. Sólo modificar la TP del proceso para que la página apunte a ese marco y ponerla como válida. -> Si no está en memoria, habría que traerla a memoria desde el dispositivo de respaldo. Como se usa buffering, tenemos un marco libre seguro. -> No es necesario emplear ninguna política de reemplazamiento de página. Ese proceso está desacoplado del tratamiento del fallo gracias al buffering. c) Falso. Los hilos comparten el mismo espacio virtual. De hecho, comparten prácticamente todas las regiones (excepto la pila, pero todas las pilas residen en el mismo espacio virtual). Cuestión 4. a. i. Reloj del sistema, funciona con una batería y mantiene la fecha y hora con el sistema apagado. El reloj temporizador produce interrupciones periódicamente, que se utilizarán para distintos propósitos (temporizadores, estadísticas, planificación) ii. Ninguno de los dos, aunque su programación se realiza escribiendo en registros de E/S y usa interrupciones para notificar sus eventos. Pero no tiene sentido pensar en un acceso aleatorio (de tamaño fijo) o secuencial al dispositivo. iii. Sí. Es un contador que, al llegar a 0, produce una interrupción. iv. Sí (para planificaciones tipo round-robin) b. i. Falso. En esos casos es contraproducente ii. Cierto. c. Se usa RAID5 por la distribución de bloques de paridad entre discos. Para una escritura, leeremos el bloque del disco destino, lo modificaremos (escritura); leeremos el disco que contenga el bloque de paridad correspodiente, recalcularemos la paridad y escribiremos de nuevo el bloque (otra escritura). Cuestión 5. a. Fichero regular -> lseek aplicable. EOF: final de fichero Directorio -> lseek: no. EOF: final de la lista de entradas Tubería -> lseek: no. EOF: se devuelve en una lectura si no hay escritores en el extremo de escritura Enlace simbólico -> lseek: no (no sobre el enlace; sí si el fichero enlazado es regular). EOF: depende del fichero apuntado Dispositivo (bloques o caracteres) -> lseek: no. EOF: Depende del dispositivo b. La lectura de un i-nodo de disco incluiría parte de la información del fichero. Para directorios, puede incluir la lista de muchos de sus ficheros, evitando una segunda lectura. La desventaja es que traemos más datos potencialmente inútiles por cada lectura de nodo-i. Además, si el fichero está vacío, desperdiciaremos esos 512 bytes. En el caso mejor para el tratamiento de la ruta propuesta bastaría con 3 lecturas (los nodos-i de home, pepe y practica2) para conocer el número de nodo-i de “prog.c” (con otra lectura, tendríamos el nodo-i de prog.c)