Preguntas cortas (justifica todas las respuestas) (2 puntos) 1. Define qué es la buffer cache, qué tipo de información encontramos y cuál es su objetivo 2. Explica qué ventajas e inconvenientes tendría tener un sistema de asignación en disco que definiera bloques de tamaño variable respecto al sistema de asignación que hemos explicado en clase en el cual los bloques de disco son del mismo tamaño. Ventajas: Inconvenientes: 3. Si tenemos una máquina con cuatro CPUs y queremos que en cada CPU se pueda ejecutar un thread de un proceso diferente, Es suficiente con tener una MMU o necesitamos una por CPU? 4. Si el fichero A tiene en su bloque de datos el siguiente contenido: /home/usr/pedro.txt Y sabemos que /home/usr/pedro.txt es un fichero de datos que existe en el sistema de ficheros. Suponed que estamos haciendo un open de A y el open ya ha leído su inodo. El comportamiento del open a partir de este punto depende del tipo de fichero de A. Indica qué dos comportamientos podría tener y con qué tipo de fichero se correspondería cada uno. 1
Procesos y ficheros (justifica todas las respuestas) (3 puntos) Queremos implementar un código que copie el contenido del fichero F1 en F2 en paralelo en una máquina que dispone de 4 CPUs. Para ello queremos repartir la copia entre 4 procesos distintos. Nos proponen el siguiente fragmento de código y se pide que contestes justificando tus respuestas a las siguientes preguntas. NOTA: F1 y F2 ya existen en el momento de ejecutar el código. El tamaño de F2 es el mismo que el de F1, pero su contenido es todo 0 s. Asume que ninguna llamada a sistema de este código devuelve error. 1. i=0;pid=0; 2. while((i<3) &&(pid==0)){ i++; pid=fork();} 3. fd_in=open( F1,O_RDONLY); 4. fd_out=open( F2,O_WRONLY); 5. while(read(fd_in,&c,sizeof(char)){ 6. write(fd_out,&c,sizeof(char)); 7. } 1. Analiza la jerarquía de procesos que genera este código para ver si realmente es la deseada. Queremos que la copia la realicen 4 procesos concurrentes. Dibuja la jerarquía e indica si cumple las especificaciones (en cuanto a procesos). Indica, además, quiénes son los que participan en la copia del fichero. 2
2. Dibuja el estado de las tablas de entrada/salida de todos los procesos asumiendo que los procesos que copian están al inicio del bucle (línea 5) (os damos el estado inicial del proceso inicial): T. canales T. Ficheros abiertos T. inodos 0 0 #refs Modo Punt l/e Ent T. inodos #refs inodo 1 0 0 3 rw -- 0 0 1 i-tty 2 0 3
3. Nos dicen que el fichero F1 tiene un tamaño de 10.000 bytes y sabemos que el tamaño del bloque de disco es de 512 bytes. Sabemos además que el sistema implementa la optimización de buffer cache compartida para inodos y bloques de datos (sabemos que la buffer cache es los suficientemente grande como para albergar todos los bloques de disco de este ejercicio). a. Podemos saber exactamente cuántos accesos a disco realizará este código, considerando todos los procesos, para leer el fichero F1? En caso afirmativo indica cuantos y en caso negativo justifícalo. b. Podemos saber exactamente cuántos bytes leerá cada proceso? c. Se cumplen las especificaciones de que el fichero F2 sea exactamente igual que F1? (analiza sólo este aspecto en esta pregunta) d. Finalmente, analiza si este código tiene algún fallo respecto a lo que queríamos conseguir y en ese caso explica brevemente qué modificaciones harías para arreglarlo. 4
Gestión de memoria (justifica todas las respuestas) (3 puntos) En un proceso con varios threads, uno de ellos ejecuta el código de la siguiente función (la línea 4 es el único malloc del código): 1. int *v; 2. void * func_thread(void *p) 3. { 4. v=(int *)malloc(10.000*sizeof(int)); 5. // Usamos v y otros calculos 6. } 1. Si observamos el ejecutable de este programa, En qué sección del ejecutable encontraremos la variable v? 2. En qué región de memoria del espacio lógico del proceso estará declarada la variable v? 3. En qué región de memoria podremos encontrar la memoria reservada por malloc? 4. Esa nueva zona de memoria, será accesible por otros threads? Podría formar parte de una región crítica? 5. Nos dan los siguientes datos sobre nuestro programa y sobre el sistema: El primer malloc siempre reserva un espacio 10 veces mayor que el espacio pedido La librería de C necesita 4096 bytes para sus datos de gestión. El vector v se accede desde otros threads (el programa tiene 10 threads) El espacio lógico del proceso es 3kb de código, 4Kb para cada pila, y sabemos que no hay más variables globales ni más mallocs Un PCB ocupa 4096 bytes para un proceso con un thread y un extra de 4096 bytes por thread adicional. 5
El sistema implementa la optimización de COW No se comparten páginas entre regiones. Calcula el espacio lógico que ocupará nuestro proceso y el espacio físico que necesitará reservar el kernel para su ejecución. (Indícalo por regiones y separado espacio de usuario y espacio de kernel) Usuario Espacio lógico: Espacio físico: Kernel Espacio lógico: Espacio físico: 6
Signals (justifica todas las respuestas) (2 puntos) Tenemos el siguiente código (se omite el tratamiento de errores para facilitar la legibilidad) en el que un proceso principal crea a un proceso hijo. 1. void trat_signal (int s) { 2. write(1, Fin Tiempo!\n, 12); 3. exit(1); 4. } 5. main (){ 6. int pid, status; 7. int fd_pipe[2]; 8. char c; 9. signal (SIGALRM, trat_signal); 10. pipe (fd_pipe); 11. pid = fork(); 12. if (pid >0) { 13. 14. write(fd_pipe[1], soy tu padre\n, 13); 15. waitpid(-1,null, 0); 16. 17. } else { 18. alarm(2); 19. while (read(fd_pipe[0], &c, sizeof(c)) > 0) 20. write(1, &c, sizeof(c)); 21. alarm(0); 22. } 23. write(1, Fin\n,4); 24. } Suponiendo que la comunicación del mensaje soy tu padre\n tarda 1 milisegundo (por tiempo de comunicación entendemos el tiempo necesario para que el receptor lea el mensaje y lo trate), contesta razonadamente a las siguientes preguntas: 1. Qué mensajes veremos en salida estándar? Indica qué proceso (el principal o el hijo) escribirá cada mensaje. 2. Suponiendo que modificamos este código y movemos la llamada a sistema alarm(2) de la línea 18 a la línea 13, y la llamada a sistema alarm(0) de la línea 21 a la 16, qué mensajes veremos en salida estándar? Indica qué proceso (el principal o el hijo) escribirá cada mensaje. 7
3. Suponiendo que sobre el código original, sin hacer ningún cambio, eliminamos ahora la llamada signal de la línea 9, qué mensajes veremos en salida estándar? Indica qué proceso (el principal o el hijo) escribirá cada mensaje. 4. Suponiendo que sobre el código original, sin hacer ningún cambio, movemos ahora la llamada signal de la línea 9 la línea 13, qué mensajes veremos en salida estándar? Indica qué proceso (el principal o el hijo) escribirá cada mensaje. 8