Las notas se publicaran el día 25 de junio (lunes) y la revisión será el martes 26 de junio a las 12:00. Pondremos una nota en el racó con el aula de la revisión. Preguntas cortas (justifica todas las respuestas) (1 punto) 1. Cuáles son las dos principales funcionalidades de la Memory Management Unit (MMU)? (indica cuáles son y en qué consisten) 2. Explica qué aporta la optimización de la memoria virtual respecto a tener simplemente paginación y carga bajo demanda Sincronización (justifica todas las respuestas) (2 puntos) Dado los siguientes códigos Código 1 int recibido=0; void f(int s) { recibido=1; } void main() { signal(sigusr1,f); while(recibido==0); recibido=0; } Código 2 void f(int s) { } void main() { signal(sigusr1,f); pause(); } Contesta a las siguientes preguntas: 1. Cuál de los dos códigos corresponde a una espera activa? 1
2. Es necesaria la reprogramación del signal SIGUSR1 en el código 2? Qué pasaría si no lo hacemos? 3. En qué región de memoria podremos encontrar la variable recibido? 4. Habrá alguna diferencia de comportamiento entre el código 1 y el 2 si sabemos que estos dos códigos, durante su ejecución, recibirán un único evento SIGUSR1? (en caso afirmativo indica cuál sería el más indicado y por qué) 2
Sistemas de ficheros (3 puntos) (justifica todas las respuestas) Supón un sistema de ficheros basado en inodos que tiene la siguiente estructura (los cuadrados indican directorios, entre paréntesis hemos puesto el número de inodo): /(0) home (1) applications (6) usr1(2) usr2(4) A (7) A(3) B(5) B (5) Sabemos que: /home/usr1/a es un soft-link a /applications/a /home/usr2/b es un hard-link a /applications/b /applications/b es un fichero vacío /applications/a ocupa 1000 bytes Cada directorio y cada inodo ocupan 1 bloque de disco El tamaño de un bloque de disco es de 512bytes Y ejecutamos la siguiente secuencia de código: 1. char c[100];int i,fd_in,fd_out,ret; 2. fd_in=open( /home/usr1/a,o_rdonly); 3. fd_out=open( /home/usr2/b,o_wronly); 4. ret=read(fd_in,c,sizeof(c)); 5. while(ret>0){ 6. for(i=0;i<ret;i++) write(fd_out,&c[i],1); 7. ret=read(fd_in,c,sizeof(c)); 8. } Contesta las siguientes preguntas : 1. Qué inodo(s) cargaremos en la tabla de inodos en memoria al ejecutar la llamada a sistema de la línea 2? 2. Cuántos y cuáles accesos a disco deberemos hacer para ejecutar la llamada a sistema de la línea 2? Indica cuáles corresponden a inodos y cuáles a bloques de datos (aunque no pongas el número de los bloques de datos). Asume que no hay buffer cache. 3
3. Si sabemos que una llamada a sistema tarda 10ms, Cuánto tiempo invertirá este código (EN TOTAL) sólo en llamadas a sistema? (Indica el coste en ms al lado de cada línea de código y el total al final) 1. char c[100]; int i,fd_in,fd_out,ret; 2. fd_in=open( /home/usr1/a,o_rdonly); 3. fd_out=open( /home/usr2/b,o_wronly); 4. ret=read(fd_in,c,sizeof(c)); 5. while(ret>0){ 6. for(i=0;i<ret;i++) write(fd_out,&c[i],1); 7. ret=read(fd_in,c,sizeof(c)); 8. } TOTAL= 4. Cuántos accesos a disco (en total) realizará el bucle de las líneas 5 a 8 en el caso de a. No tener buffer cache b. Tener una buffer cache de 1000 bloques y sabiendo que las escrituras se sincronizan en disco al cerrar el fichero. 4
Comunicación entre procesos (4 puntos) (justifica todas las respuestas) Tenemos los siguientes códigos prog1.c y prog2.c, de los que omitimos la gestión de errores para facilitar la legibilidad: 1. / * codigo de prog1.c */ 2. main() { 3. 4. int pid_h; 5. int pipe_fd[2]; 6. char buf [80]; 7. 8. pipe(pipe_fd); 9. 10. pid_h =fork(); 11. 12. dup2(pipe_fd[0], 0); 13. dup2(pipe_fd[1], 1); 14. 15. close(pipe_fd[0]); 16. close(pipe_fd[1]); 17. 18. sprintf(buf, "%d", pid_h); 19. 20. execlp("./prog2", "prog2", buf, (char *) NULL); 21. 22. 23. } 24. 1. / * codigo de prog2.c */ 2. int turno_escr; 3. 4. void trat_sigusr1(int signum) { 5. turno_escr = 1; 6. } 7. 8. main (int argc, char *argv[]) { 9. 10. char buf [80]; 11. int pid_dest; 12. int i,ret,valor_rec; 13. int valor = getpid(); 14. 15. signal(sigusr1, trat_sigusr1); 16. 17. pid_dest = atoi(argv[1]); 18. 19. if (pid_dest == 0) { 20. pid_dest = getppid(); 21. write(1, &valor,sizeof(valor)); 22. turno_escr = 0; 23. kill(pid_dest,sigusr1); 24. valor ++; 25. 26. } else { 27. turno_escr = 0; 28. } 29. 30. for (i = 0; i< 5; i++) { 31. while (!turno_escr); 32. ret=read (0,&valor_rec,sizeof(valor_rec)); 33. sprintf(buf, %d,valor_rec); 34. write(2,buf,ret); 35. write(2,"\n",1); 36. write(1,&valor,sizeof(valor)); 37. turno_escr = 0; 38. kill(pid_dest,sigusr1); 39. valor ++; 40. 41. } 42. 43. } 44. Supón que en el directorio actual de trabajo tenemos los ejecutables prog1 y prog2, y que ejecutamos el siguiente comando: %./prog1 Contesta razonadamente a las siguientes preguntas a) Cuántos procesos se crearán? Cuántas pipes? 5
b) Representa la jerarquía de procesos que creará este programa en ejecución. Asigna a cada proceso un pid para poder referirte a ellos en el resto de preguntas. Representa también las pipes que se crean indicando qué proceso(s) lee(n) de cada una y qué proceso(s) escribe(n) en cada una. c) Qué proceso(s) ejecutará(n) el código de prog2? d) Qué mensajes aparecerán en el terminal? e) Describe brevemente el funcionamiento de este código. Para qué se están utilizando los signals? f) Supón que el código prog1 ocupa 1KB y el código de prog2 ocupa 4KB. La máquina en la que ejecutamos estos códigos tiene un sistema de memoria basado en paginación, las páginas miden 4KB y utiliza la optimización copy-on-write en el fork. Cuánta memoria necesitaremos para soportar el código de todos los procesos simultáneamente, suponiendo que cada proceso se encuentra en la última instrucción antes de acabar su ejecución? 6
g) La siguiente figura representa el estado de la tabla de canales, la tabla de ficheros abiertos y la tabla de inodos al inicio de la ejecución de este programa. Completa la figura representando el estado de las tablas de canales de cada proceso, la tabla de ficheros abiertos y la tabla de inodos, suponiendo que todos los procesos están ejecutando la última instrucción antes de acabar su ejecución. 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 7