SlideShare una empresa de Scribd logo
@ibaumo
100 Ejercicios resueltos
                             @ibaumo
                                 de Sistemas Operativos
                                 José Ribelles Miguel
                                 José Martínez Sotoca
                                 Pedro García Sevilla

                                                                      Departament de llenguatges i sistemes informàtics


                                                                         Codi d’assignatura IG11




J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7                      100 Ejercicios resueltos de Sistemas Operativos - UJI
@ibaumo
Edita: Publicacions de la Universitat Jaume I. Servei de Comunicació i Publicacions
   Campus del Riu Sec. Edifici Rectorat i Serveis Centrals. 12071 Castelló de la Plana
   http://www.tenda.uji.es	 e-mail: publicacions@uji.es

Col·lecció Sapientia, 30
www.sapientia.uji.es

ISBN: 978-84-693-0148-7



Aquest text està subjecte a una llicència Reconeixement-NoComercial-CompartirIgual de Creative
Commons, que permet copiar, distribuir i comunicar públicament l’obra sempre que especifique
l’autor i el nom de la publicació i sense objectius comercials, i també permet crear obres derivades,
sempre que siguen distribuïdes amb aquesta mateixa llicència.
http://creativecommons.org/licenses/by-nc-sa/2.5/es/deed.ca




   J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7                          100 Ejercicios resueltos de Sistemas Operativos - UJI
´
              Indice general
              ´
              Indice general
                     Prefacio	                   	            	                  	               	                   	               	                  	          	            4
              1. Procesos e Hilos                                                                                                                                        1
                 1.1. Procesos . . . . .                      .    .   .   .    . . . . .         .    .   .   .    . . . . .         .    .   .   .    . . . .          1
              1. 1.2. Planificaci´ n . .
                 Procesos e Hiloso                            .    .   .   .    . . . . .         .    .   .   .    . . . . .         .    .   .   .    . . . .         18     6
                 1.3. Hilos . . . .. . . . ..
                 1.1. Procesos                               ..   ..   .
                                                                       .   ..   .. .. . . . ..   ..   ..   .
                                                                                                           .   ..   .. .. . . . ..   ..   ..   .
                                                                                                                                               .   ..   .. .. . . . . . 13 . . 6
                                                                                                                                                                        1.
                     1.2. Planificaci´ n . . . . . . . . . . . .
                                    o
              2. Comunicaci´ n y Sincronizaci´ n de Procesos
                             o                          o
                                                                                                                     . . . . . . . . . . . . . 15 . . 13 8     .
                 1.3. Tuber´as. .. .. . . . .. .. .. . .. .. .. . . . .. .. .. . ..
                 2.1.  Hilos
                           ı                         .                         .                                    .. .. . . . .. .. .. . .. .. .. . . . . . 15 . . 1813
                                                                                                                                         .                     .
                 2.2. Sem´ foros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
                         a                                                                                                                                             19
              2. Comunicaci´ n y Sincronizaci´ n de Procesos
                                 o                   o                                                                     2015
              3. Gesti´ n de Archivos y Directorios . . . . . . . . . . . . . . . . . . . 29 . . 2015
                 2.1. o Tuber´as . . . . . . . . .
                               ı                                                                                     .
                 3.1. Sistemas de Archivos . .. .. .. . . . .. .. .. . .. .. .. . . . .. .. .. . .. .. .. . . . . . 29 . . 2419
                 2.2. Sem´ foros . . . .
                             a              .                        .                         .                     .
                    3.2. Archivos y Directorios . . . . . . . . . . . . . . . . . . . . . . .                                                                          31
              3. Gesti´ n de Archivos y Directorios
                      o                                                                                                                                                        33    29
              4. Gesti´ n de Memoria
                      o                                                                                                                                                 35




                             @ibaumo
                 3.1. Sistemas de Archivos . . . .                                               .    .    .   . . . . . . . . .                         . . . . . . . . 3329
                 4.1. Paginaci´ n . . . . . . . . . . . . .
                               o                                                                  .    .   .   . . . . . . . . . .                      . . . . 35
                 3.2. Pol´ticas de y Directorios. .. . . . ..
                 4.2.   Archivos Reemplazo .
                          ı                                                                      ..   ..   .
                                                                                                           .   .. .. .. . . . .. .. .. . ..
                                                                                                                                       .                .. .. . . . . . 36 . . 3531
                                                                                                                                                                         .

              5. Ejerciciosde Memoria
              4. Gesti´ n Generales
                       o                                                                      3835                                                                     39
                 4.1. Paginaci´ n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3835
                                 o
              6. Solucionesıticas de Reemplazo . . . . . . . . . . . . . . . . . . . . 57 . .
                 4.2. Pol´                                                              .     3936

              5. Ejercicios Generales                                                                                                                                           4139

              6. Soluciones                                                                                                                                                     5857




                                                                                      V




                                                                                                 V
J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7                                                                               100 Ejercicios resueltos de Sistemas Operativos - UJI
Prefacio

    Los Sistemas Operativos han constituido tradicionalmente una materia troncal
en los planes de estudio de todas las titulaciones de Inform´ tica. Las asignaturas
                                                                a
que desarrollan estos contenidos incluyen aspectos te´ ricos fundamentales como
                                                          o
procesos e hilos, gesti´ n de memoria, comunicaci´ n, sincronizaci´ n y sistemas de
                       o                             o                o
archivos. Adem´ s, es frecuente incluir una parte pr´ ctica que permite que el alumno
                 a                                   a
conozca no s´ lo los principios te´ ricos, sino tambi´ n c´ mo se aplican en sistemas
              o                   o                   e o
operativos reales.
    El objetivo de este libro es proporcionar suficiente material pr´ ctico para apo-
                                                                      a
yar la docencia, tanto presencial, desarrollada en clases de problemas o en labo-
ratorio, como no presencial, proporcionando al estudiante un material de apoyo al
estudio de un nivel y contenido adecuado a una asignatura real.



                              @ibaumo
    En concreto, las cuestiones, ejercicios y problemas que se recogen en este li-
bro son el resultado de su recopilaci´ n a lo largo de cuatro cursos, desde el a˜ o
                                       o                                            n
2004, del material utilizado en la asignatura de Sistemas Operativos de la Inge-
nier´a T´ cnica en Inform´ tica de Gesti´ n de la Universitat Jaume I de Castell´ n.
    ı e                    a              o                                         o
Dicha asignatura se estructura en 3 cr´ ditos de teor´a, 1,5 cr´ ditos de problemas y
                                        e              ı        e
1,5 cr´ ditos de laboratorio. No obstante, el material incluido es bastante gen´ rico
      e                                                                           e
y puede ser empleado en cualquier asignatura b´ sica de Sistemas Operativos.
                                                  a
    El contenido de este libro se divide en 6 cap´tulos cuya descripci´ n se indica a
                                                   ı                    o
continuaci´ n:
            o

   1. Gesti´ n de Procesos e Hilos: planificaci´ n de procesos, jerarqu´a de procesos
           o                                  o                       ı
      y uso de las llamadas al sistema para la gesti´ n de procesos e hilos.
                                                    o

   2. Comunicaci´ n y Sincronizaci´ n de Procesos: problemas cl´ sicos de la sec-
                    o               o                             a
      ci´ n cr´tica, productor-consumidor y lector-escritor; y llamadas al sistema
        o     ı
      para el manejo de sem´ foros y tuber´as.
                              a           ı

   3. Gesti´ n de Archivos y Directorios: sistemas de archivos tipo FAT y nodo-i,
           o
      llamadas al sistema para la gesti´ n de archivos y directorios.
                                       o

   4. Gesti´ n de Memoria: memoria virtual, paginaci´ n y pol´ticas de reemplazo.
           o                                        o        ı

   5. Problemas generales: problemas cuya resoluci´ n incluya conceptos tratados
                                                  o
      en varios de los cap´tulos anteriores.
                          ı

                                                                   III

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7            100 Ejercicios resueltos de Sistemas Operativos - UJI
6. Soluciones: en este cap´tulo se encuentran las soluciones a los ejercicios
                              ı
      planteados en todos los cap´tulos anteriores.
                                 ı

    Se ha creado la p´ gina Web http://ig11.uji.es como apoyo a este ma-
                     a
terial, para mantenerlo actualizado incluyendo m´ s ejercicios, p´ ginas de ayuda, fe
                                                  a              a
de erratas, etc.
          ´
    Por ultimo, no queremos dejar de expresar nuestro agradecimiento a los pro-
fesores Gustavo Casa˜ , Isabel Gracia y Antonio Castellanos, todos ellos del De-
                       n
partamento de Lenguajes y Sistemas Inform´ ticos de la Universitat Jaume I, que
                                              a
tambi´ n han participado en la impartici´ n de la asignatura durante otros cursos y,
       e                                 o
como no, en la elaboraci´ n de algunos de los ejercicios propuestos de este libro.
                          o

                                                                        Marzo, 2010




                               @ibaumo




  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7      100 Ejercicios resueltos de Sistemas Operativos - UJI
Cap´tulo 1
   ı

Procesos e Hilos

1.1.         Procesos
   1. Observa el siguiente c´ digo y escribe la jerarqu´a de procesos resultante.
                            o                          ı
         #include          sys/types.h
         #include          sys/wait.h
         #include          unistd.h
         #include          stdio.h
         #include          stdlib.h




                              @ibaumo
         int main (int argc, char ∗argv[]) {

             int num;
             pid t pid;

             for (num= 0; num 3; num++) {
               pid= fork();
               printf (Soy el proceso de PID %d y mi padre tiene %d de PID.n,
                       getpid(), getppid());
               if (pid!= 0)
                 break;
               srandom(getpid());
               sleep (random() %3);
             }
             if (pid!= 0)
               printf (Fin del proceso de PID %d.n, wait (NULL));

             return 0;
         }



         Ahora compila y ejecuta el c´ digo para comprobarlo. Contesta a las siguien-
                                     o
         tes preguntas:

                   ¿Por qu´ aparecen mensajes repetidos?
                          e
                   Presta atenci´ n al orden de terminaci´ n de los procesos,
                                o                        o
                       • ¿qu´ observas?
                            e
                       • ¿por qu´ ?
                                e

                                                                   1

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7                  100 Ejercicios resueltos de Sistemas Operativos - UJI
2. Observa el siguiente c´ digo y escribe la jerarqu´a de procesos resultante.
                         o                          ı
   #include          sys/types.h
   #include          sys/wait.h
   #include          unistd.h
   #include          stdio.h
   #include          stdlib.h

   int main (int argc, char ∗argv[]) {

       int num;
       pid t pid;

       srandom(getpid());
       for (num= 0; num 3; num++) {
         pid= fork();
         printf (Soy el proceso de PID %d y mi padre tiene %d de PID.n,
                   getpid(), getppid());
         if (pid== 0)
            break;
       }
       if (pid== 0)
         sleep(random() %5);
       else
         for (num= 0; num 3; num++)
            printf (Fin del proceso de PID %d.n, wait (NULL));

       return 0;
   }




                               @ibaumo
   Ahora compila y ejecuta el c´ digo para comprobarlo. Presta atenci´ n al or-
                                 o                                   o
   den de terminaci´ n de los procesos, ¿qu´ observas? ¿por qu´ ?
                   o                       e                  e

                            ´
3. Dibuja la estructura del arbol de procesos que obtendr´amos al ejecutar el
                                                         ı
   siguiente fragmento de c´ digo:
                            o
   for (num= 0; num 2; num++) {
     nuevo= fork(); /∗ 1 ∗/
     if (nuevo== 0)
       break;
   }
   nuevo= fork();         /∗ 2 ∗/
   nuevo= fork();         /∗ 3 ∗/
   printf(Soy el proceso %d y mi padre es %dn, getpid(), getppid());



4. Considerando el siguiente fragmento de c´ digo:
                                           o
   for (num= 1; num= n; num++){
     nuevo= fork();
     if ((num== n)  (nuevo== 0))
       execlp (ls, ls, -l, NULL);
   }


       a) Dibuja la jerarqu´a de procesos generada cuando se ejecuta y n es 3.
                           ı
       b) Indica en qu´ procesos se ha cambiado la imagen del proceso usando
                        e
          la funci´ n execlp.
                  o


                                                                    2

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7           100 Ejercicios resueltos de Sistemas Operativos - UJI
5. Dibuja la jerarqu´a de procesos que resulta de la ejecuci´ n del siguiente c´ di-
                    ı                                       o                  o
   go. Indica para cada nuevo proceso el valor de las variables i y j en el mo-
   mento de su creaci´ n.
                      o
   for (i= 0; i 2; i++) {
     pid= getpid();
     for (j= 0; j i+2; j++) {
       nuevo= fork();    /∗ 1 ∗/
       if (nuevo!= 0) {
         nuevo= fork(); /∗ 2 ∗/
         break;
       }
     }
     if (pid!= getpid())
       break;
   }


6. Estudia el siguiente c´ digo y escribe la jerarqu´a de procesos resultante. Des-
                         o                          ı
   pu´ s, compila y ejecuta el c´ digo para comprobarlo (deber´ s a˜ adir llamadas
      e                         o                               a n
   al sistema getpid, getppid y wait para conseguirlo).
   #include          sys/types.h
   #include          sys/wait.h
   #include          unistd.h
   #include          stdio.h
   #include          stdlib.h

   #define L1 2
   #define L2 3




                               @ibaumo
   int main (int argc, char ∗argv[]) {

       int cont1, cont2;
       pid t pid;

       for (cont2= 0; cont2 L2; cont2++) {
         for (cont1= 0; cont1 L1; cont1++) {
           pid= fork();
           if (pid== 0)
             break;
         }
         if (pid!= 0)
           break;
       }
       return 0;
   }



7. Dibuja la jerarqu´a de procesos que resulta de la ejecuci´ n del siguiente c´ di-
                    ı                                       o                   o
                                                                              ´
   go. Introduce las llamadas al sistema wait para que una vez generado el arbol
   de procesos los hijos sean esperados por sus respectivos padres. Adem´ s,      a
   haz que se informe de los tiempos de ejecuci´ n de las aplicaciones xload y
                                                  o
   kcalc que se generen as´ como del tiempo total de ejecuci´ n. Para calcular el
                           ı                                   o
   tiempo transcurrido, puedes utilizar la funci´ n time() de la librer´a est´ ndar
                                                o                       ı    a
   time.h. La llamada time(NULL) devuelve los segundos transcurridos desde
   las 00:00:00 del 1/1/1970 hasta el instante de la llamada.


                                                                    3

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7          100 Ejercicios resueltos de Sistemas Operativos - UJI
int main (int argc, char ∗argv[]) {

       int i, j;
       pid t pid, nuevo, nuevo1;
       time t ini, fin;

       for (i= 0; i 2; i++){
         pid= getpid();
         for (j= 0; j i+2; j++){
           nuevo= fork();
           if(nuevo== 0){
             break;
             nuevo1= fork();
             if(nuevo1== 0)
               execlp (xload, xload, NULL);
           }
         }
         if (pid!= getpid())
           execlp (kcalc, kcalc, NULL);
       }
       return 0;
   }



                                        ´
8. Escribe un programa que genere un arbol de procesos similar al que apa-
                                                                  ´
   rece en la figura 1.1. Los valores de profundidad y anchura del arbol ser´ n
                                                                           a
   dados como par´ metros de entrada por el usuario en cada ejecuci´ n. En el
                   a                                                o
   ejemplo, se considera que la profundidad es 5 y la anchura 3. Tu programa




                               @ibaumo
   podr´ empezar, por ejemplo, de la siguiente manera:
        a
   #include stdio.h
   #include unistd.h
   #include stdlib.h

   int main (int argc, char ∗argv[]) {

       int i;
       int prof, anch;

       if (argc!= 3) exit(0);

       profundidad= atoi(argv[1]); /∗ profundidad ∗/
       anchura=     atoi(argv[2]); /∗ anchura     ∗/

       /∗ completar aqu´ ∗/
                       ı

       printf(Soy el proceso %d y mi padre es %dn, getpid(), getppid());
       sleep (2);
       return 0;
   }

                                                                         ´
   Modifica el programa anterior para que la expansi´ n en anchura del arbol se
                                                     o
   produzca s´ lo en aquellos niveles de profundidad par (y distinta de cero). En
              o
   la figura 1.2 se muestra un ejemplo.

9. Escribe el fragmento de c´ digo que genera la jerarqu´a de procesos que se
                             o                          ı
   muestra en la figura 1.3 para profundidad n.


                                                                    4


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7            100 Ejercicios resueltos de Sistemas Operativos - UJI
´
         Figura 1.1: Arbol de profun-                                                ´
                                                                        Figura 1.2: Arbol de profun-
         didad 5 y anchura 3.                                           didad 5 y anchura 3, que s´ lo
                                                                                                   o
                                                                        se expande en anchura para
                                                                        los niveles pares distintos de
                                                                        cero.




                               @ibaumo
                 Figura 1.3: Jerarqu´a de procesos con profundidad n = 3.
                                    ı


10. Observa el siguiente fragmento de c´ digo que trata de medir el tiempo de
                                        o
    ejecuci´ n del programa prueba.exe. Indica qu´ problemas se producen, por
           o                                     e
    qu´ y c´ mo resolverlos.
       e o
     time t inicio= 0, fin= 0;

     if (fork()!= 0) {
       wait (NULL);
       fin= time (NULL);
       printf (Tiempo empleado: %ldn, fin-inicio);
     } else {
       inicio= time (NULL);
       execlp (prueba.exe, prueba.exe, NULL);
     }



11. El programa siguiente pretende lanzar a ejecuci´ n una calculadora, kcalc, y
                                                     o
    otra aplicaci´ n, xload, utilizando dos llamadas al sistema execlp consecuti-
                 o
    vas. Antes de compilar y ejecutar el programa, piensa qu´ va a ocurrir.
                                                              e
     #include           sys/types.h
     #include           sys/wait.h
     #include           unistd.h
     #include           stdio.h
     #include           stdlib.h



                                                                    5

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7           10                     100 Ejercicios resueltos de Sistemas Operativos - UJI
int main (int argc, char ∗argv[]) {

         execlp         (kcalc, kcalc, NULL);
         printf         (¿Se imprimira este mensaje?n);
         execlp         (xload, xload, NULL);
         printf         (¿Y este otro?n);
         return         0;
     }

     Ahora, comp´lalo y ejecut´ lo y observa qu´ ocurre. ¿Has acertado? ¿Sabes
                  ı            a               e
     por qu´ ? Modif´calo para que el usuario vea las dos aplicaciones al mismo
           e        ı
     tiempo. Haz adem´ s que el proceso principal espere a la finalizaci´ n de am-
                       a                                               o
     bas aplicaciones e informe de la finalizaci´ n de cada una especificando si
                                               o
     termin´ kcalc o xload.
           o

12. A˜ ade al programa resultado del problema 11 el c´ lculo del tiempo que cada
      n                                               a
    uno de los procesos ha estado en ejecuci´ n, incluido el proceso padre, y sea
                                             o
    el proceso padre el que informe de ellos antes de finalizar.

13. Escribe un programa en C que pida por teclado dos cadenas de caracteres y
    despu´ s escriba cada cadena por pantalla car´ cter a car´ cter. La escritura de
          e                                       a          a
    cada cadena deber´ hacerla un proceso diferente. Recuerda utilizar la funci´ n
                       a                                                          o
    fflush despu´ s de escribir cada car´ cter. El proceso padre deber´ esperar a
                e                       a                               a
    que termine el proceso hijo. Obtendr´ s resultados interesantes si despu´ s de
                                          a                                    e
    escribir cada car´ cter introduces un retardo aleatorio para simular que su
                      a



                               @ibaumo
    escritura consume un cierto tiempo.

14. El siguiente programa en C lee repetidamente por teclado el nombre de un
    programa a ejecutar y pregunta si se debe esperar a que termine la ejecuci´ n
                                                                              o
    del mismo. El programa termina de ejecutarse cuando el usuario introduce
    como programa a ejecutar salir.
     #include stdio.h
     #include string.h
     #include stdbool.h

     int main (int argc, char ∗argv[]) {

         bool fin= false;
         char nombre prog[50], esperar[5];
         while (!fin) {
           printf (Programa: ); scanf ( %s, nombre prog);
           if (strcmp(nombre prog, salir)!=0) {
             printf (Esperar? ); scanf ( %s, esperar);

                 /∗ completar aqu´ ∗/
                                 ı

             }
             else
               fin= true;
         }

         return 0;
     }



                                                                    6


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7       11   100 Ejercicios resueltos de Sistemas Operativos - UJI
Realiza las modificaciones oportunas para que el programa cree un nuevo
     proceso que se encargue de ejecutar el programa indicado. Se debe utilizar
     la variable PATH para buscar el programa a ejecutar. Si dicho programa no
     se pudiese ejecutar por cualquier motivo, se deber´ mostrar un mensaje de
                                                           a
     error e informar al usuario del valor actual de la variable PATH. En cualquier
     caso, el proceso inicial esperar´ o no la finalizaci´ n del programa dado en
                                      a                   o
     funci´ n de lo que el usuario haya indicado. Cuando no se espere la finaliza-
           o
     ci´ n del programa dado, se debe indicar el identificador del proceso creado.
       o
     Para comprobar el correcto funcionamiento de este programa se aconseja es-
     cribir otro programa que muestre por pantalla los n´ meros del 1 al 20 con
                                                             u
                                                                   ´
     un intervalo de 1 segundo entre cada n´ mero. Pide que sea este el programa
                                              u
     que se ejecute, unas veces esperando su finalizaci´ n y otras no.
                                                         o

15. El siguiente programa recibe como par´ metro de entrada un n´ mero entero
                                           a                    u
    y muestra como resultado su factorial.
     #include stdio.h
     #include stdlib.h
     #include unistd.h

     long long int factorial (int n) {

         long long int resultado= 1;
         int num;




                               @ibaumo
         for (num= 2; num= n; num++) {
           resultado= resultado∗ num;
           printf (Factorial de %d, resultado parcial %lldn, n, resultado);
           sleep (random() %3);
         }
         return resultado;
     }

     int main (int argc, char ∗argv[]) {

         if (argc== 2)
           printf (El factorial de %s es %lldn,
                    argv[1], factorial (atoi (argv[1])));
         return 0;
     }


         a) Escr´belo, comp´lalo y ejec´ talo para comprobar su funcionamiento.
                ı          ı           u
         b) Escribe un nuevo programa que reciba dos n´ meros enteros como par´ me-
                                                       u                        a
            tros de entrada y cree dos procesos de manera que cada uno calcule el
            factorial de uno de los n´ meros, de forma concurrente, y utilizando el
                                     u
            fichero ejecutable obtenido en el apartado anterior.
                                             ´
         c) Haz que el proceso padre sea el ultimo en terminar, es decir, que espere
            a la terminaci´ n de sus procesos hijos.
                          o

16. Generaliza la soluci´ n del problema 15 de manera que no est´ limitado a 2
                         o                                          e
    el n´ mero de factoriales a calcular. Procede de la siguiente manera:
        u

                                                                    7

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7       12       100 Ejercicios resueltos de Sistemas Operativos - UJI
a) Crea un proceso por cada factorial a calcular, y que todos los procesos
               se ejecuten de forma concurrente.
            b) El proceso padre deber´ esperar a todos los procesos hijos y mostrar un
                                     a
               mensaje a medida que vayan terminando indicando el PID del proceso
               finalizado.
            c) Modif´calo para que no se imprima mensaje cuando el primer proceso
                     ı
               hijo finalice, pero si para los dem´ s.
                                                 a

 17. Escribe un programa, al que llamar´ s tiempo.c, cuyo objetivo es lanzar a eje-
                                       a
         o                                a                ı        ´
     cuci´ n un segundo programa que ser´ indicado en la l´nea de ordenes (junto
     con sus argumentos) como por ejemplo: $ tiempo ls -R -l /tmp. Adem´ s, haz
                                                                           a
     que se contabilice de forma aproximada el tiempo que tarda en ejecutarse el
     segundo programa.


1.2.        Planificaci´ n
                      o
   Para la realizaci´ n de los siguientes ejercicios ten en cuenta que:
                    o
        La simulaci´ n comienza siempre con una interrupci´ n de reloj.
                   o                                      o

        Cuando un proceso cambia su estado de bloqueado a listo, y si en el enun-
        ciado no se indica nada al respecto, el proceso se situar´ siempre al final de
                                                                 a



                              @ibaumo
        la cola de espera.

 18. Considera un sistema con las siguientes caracter´sticas:
                                                     ı

                  Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                       o
                  de dos interrupciones de reloj.
                  La interrupci´ n de reloj se produce cada 4 unidades de tiempo.
                               o
                  Las rutinas de tratamiento de las interrupciones hardware y de la inte-
                  rrupci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamien-
                         o
                  to de la interrupci´ n software consume 2 unidades de tiempo.
                                      o
                  Existen dos dispositivos de entrada/salida sobre los que se pueden rea-
                  lizar operaciones en paralelo.
                  Los niveles de prioridad de las interrupciones son:
                       - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo 1
                                    a                          o
                         (IH1)
                       - Nivel 1: Interrupci´ n de reloj (IR)
                                            o
                       - Nivel 2: Interrupci´ n hardware del dispositivo 2 (IH2)
                                            o
                       - Nivel 3 (menos prioritario): Interrupci´ n software (IS)
                                                                  o
        Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini-
                                           a
        cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro-
                         a
        cesos es el siguiente:

                                                                   8

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7       13      100 Ejercicios resueltos de Sistemas Operativos - UJI
Proc A         CPU (2ut.)             E/S D1 (2ut.)        CPU (3ut.)   E/S D2 (5ut.)   CPU (1ut)

             Proc B         CPU (5ut.)             E/S D1 (1ut.)        CPU (1ut.)

     Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
                e                   o      a
     tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S
                           e
     est´ n siendo utilizados.
        a

19. Considera un sistema con las siguientes caracter´sticas:
                                                    ı

               Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                    o
               de dos interrupciones de reloj.
               La interrupci´ n de reloj se produce cada 5 unidades de tiempo.
                            o
               Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup-
                                                          o
               ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento
                 o
               de la interrupci´ n software consume 2 unidades de tiempo.
                               o
               Existe un dispositivo de entrada/salida sobre el que se pueden realizar
               operaciones en paralelo con la CPU.
               Los niveles de prioridad de las interrupciones son:
                    - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de
                                 a                          o
                      E/S (IH)
                    - Nivel 1: Interrupci´ n de reloj (IR)
                                         o



                               @ibaumo
                    - Nivel 2 (menos prioritario): Interrupci´ n software (IS)
                                                               o
     Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini-
                                        a
     cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro-
                      a
     cesos es el siguiente:

                  Proc A          CPU (3ut.)            E/S (3ut.)      CPU (2ut.)   E/S (1ut.)   CPU (1ut.)

                  Proc B          CPU (8ut.)            E/S (1ut.)      CPU (1ut.)

     Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
                e                   o      a
     tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S
                           e
     est´ n siendo utilizados.
        a

20. Considera un sistema con las siguientes caracter´sticas:
                                                    ı

               Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                    o
               de dos interrupciones de reloj.
               La interrupci´ n de reloj se produce cada 4 unidades de tiempo.
                            o
               Las rutinas de tratamiento de las interrupciones hardware y de la inte-
               rrupci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamien-
                      o
               to de la interrupci´ n software consume 2 unidades de tiempo.
                                   o
               Existen un dispositivo de entrada/salida sobre el que se pueden realizar
               operaciones en paralelo con la CPU.

                                                                    9

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7             14                       100 Ejercicios resueltos de Sistemas Operativos - UJI
Los niveles de prioridad de las interrupciones son:
                    - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de
                                 a                          o
                      E/S (IH)
                    - Nivel 1: Interrupci´ n de reloj (IR)
                                         o
                    - Nivel 2 (menos prioritario): Interrupci´ n software (IS)
                                                               o
     Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini-
                                        a
     cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro-
                      a
     cesos es el siguiente:
                                       Proc A          CPU (6ut.)        E/S (1ut.)    CPU (2ut.)

                                       Proc B          CPU (2ut.)        E/S (6ut.)    CPU (3ut.)

     Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
                e                   o      a
     tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S
                           e
     est´ n siendo utilizados.
        a
21. Considera un sistema con las siguientes caracter´sticas:
                                                    ı
               Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                    o
               de dos interrupciones de reloj.
               La interrupci´ n de reloj se produce cada 4 unidades de tiempo.
                            o
               Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup-
                                                          o



                               @ibaumo
               ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento
                 o
               de la interrupci´ n software consume 1 unidad de tiempo.
                               o
               Existe un dispositivo de entrada/salida sobre el que se pueden realizar
               operaciones en paralelo con la CPU.
               Los niveles de prioridad de las interrupciones son:
                    - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de
                                 a                          o
                      E/S (IH)
                    - Nivel 1: Interrupci´ n de reloj (IR)
                                         o
                    - Nivel 2 (menos prioritario): Interrupci´ n software (IS)
                                                               o
     Existen tres procesos A, B y C que est´ n listos para ejecutar, y que, ini-
                                             a
     cialmente, ser´ n atendidos en ese orden. El modelo que siguen estos tres
                    a
     procesos es el siguiente:
                                      Proc A          CPU (3ut.)         E/S (10ut.)   CPU (4ut.)

                                      Proc B          CPU (6ut.)

                                      Proc C          CPU (3ut.)         E/S (4ut.)    CPU (1ut.)

     Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
                e                      o    a
     tiempo teniendo en cuenta que cuando un proceso pasa de bloqueado a listo
     se sit´ a al principio de la cola de espera. Indica tambi´ n aquellos instantes
           u                                                  e
     en los que los dispositivos de E/S est´ n siendo utilizados.
                                            a

                                                                    10

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7               15                  100 Ejercicios resueltos de Sistemas Operativos - UJI
22. Considera un sistema con las siguientes caracter´sticas:
                                                    ı

               Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                    o
               de dos interrupciones de reloj.
               La interrupci´ n de reloj se produce cada 4 unidades de tiempo.
                            o
               Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup-
                                                          o
               ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento
                 o
               de la interrupci´ n software consume 2 unidades de tiempo.
                               o
               Existe un dispositivo de entrada/salida sobre el que se pueden realizar
               operaciones en paralelo con la CPU.
               Los niveles de prioridad de las interrupciones son:
                    - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de
                                 a                          o
                      E/S (IH)
                    - Nivel 1: Interrupci´ n de reloj (IR)
                                         o
                    - Nivel 2 (menos prioritario): Interrupci´ n software (IS)
                                                               o
     Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini-
                                        a
     cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro-
                      a
     cesos es el siguiente:

                  Proc A          CPU (3ut.)            E/S (1ut.)       CPU (1ut.)   E/S (1ut.)   CPU (1ut.)




                               @ibaumo
                  Proc B          CPU (4ut.)

     Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
                e                   o      a
     tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S
                           e
     est´ n siendo utilizados.
        a

23. Considera un sistema con las siguientes caracter´sticas:
                                                    ı

               Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                    o
               de dos interrupciones de reloj.
               La interrupci´ n de reloj se produce cada 4 unidades de tiempo.
                            o
               Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup-
                                                          o
               ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento
                 o
               de la interrupci´ n software consume 1 unidad de tiempo.
                               o
               Existe un dispositivo de entrada/salida sobre el que se pueden realizar
               operaciones en paralelo con la CPU.
               Los niveles de prioridad de las interrupciones son:
                    - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de
                                 a                          o
                      E/S (IH)
                    - Nivel 1: Interrupci´ n de reloj (IR)
                                         o
                    - Nivel 2 (menos prioritario): Interrupci´ n software (IS)
                                                               o

                                                                    11

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7              16                       100 Ejercicios resueltos de Sistemas Operativos - UJI
Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini-
                                        a
     cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro-
                      a
     cesos es el siguiente:

                 Proc A          CPU (14ut.)

                 Proc B           CPU (2ut.)             E/S (1ut.)       CPU (1ut.)     E/S (1ut.)   CPU (1ut.)

     Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
                e                   o      a
     tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S
                           e
     est´ n siendo utilizados.
        a

24. Considera un sistema con las siguientes caracter´sticas:
                                                    ı

               Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                    o
               de dos interrupciones de reloj.
               La interrupci´ n de reloj se produce cada 4 unidades de tiempo.
                            o
               Las rutinas de tratamiento de las interrupciones hardware y de la inte-
               rrupci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamien-
                      o
               to de la interrupci´ n software consume 2 unidades de tiempo.
                                   o
               Existen dos dispositivos de entrada/salida sobre los que se pueden rea-
               lizar operaciones en paralelo.




                               @ibaumo
               Los niveles de prioridad de las interrupciones son:
                    - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo 1
                                 a                          o
                      (IH1)
                    - Nivel 1: Interrupci´ n hardware del dispositivo 2 (IH2)
                                         o
                    - Nivel 2: Interrupci´ n de reloj (IR)
                                         o
                    - Nivel 3 (menos prioritario): Interrupci´ n software (IS)
                                                               o
     Existen tres procesos A, B y C que est´ n listos para ejecutar en ese mismo
                                           a
     orden. El modelo que siguen estos dos procesos es el siguiente:

                                    Proc A          CPU (1ut.)           E/S D1 (8ut.)   CPU (1ut.)

                                    Proc B          CPU (2ut.)           E/S D2 (2ut.)   CPU (7ut.)

                                    Proc C          CPU (4ut.)

     Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
               e                      o     a
     tiempo teniendo en cuenta adem´ s que cuando los procesos pasan de blo-
                                        a
     queados a listos se sit´ an al principio de la cola de espera. Indica tambi´ n
                            u                                                     e
     aquellos instantes en los que los dispositivos de E/S est´ n siendo utilizados.
                                                              a

25. Considera un sistema con las siguientes caracter´sticas:
                                                    ı

               Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum
                                                    o
               de dos interrupciones de reloj.

                                                                    12

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7                17                       100 Ejercicios resueltos de Sistemas Operativos - UJI
La interrupci´ n de reloj se produce cada 5 unidades de tiempo.
                               o
                  Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup-
                                                             o
                  ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento
                    o
                  de la interrupci´ n software consume 1 unidad de tiempo.
                                  o
                  Existe un dispositivo de entrada/salida sobre el que se pueden realizar
                  operaciones en paralelo con la CPU.
                  Los niveles de prioridad de las interrupciones son:
                       - Nivel 0 (m´ s prioritario): Interrupci´ n de reloj (IR)
                                    a                          o
                       - Nivel 1: Interrupci´ n hardware del dispositivo de E/S (IH)
                                            o
                       - Nivel 2 (menos prioritario): Interrupci´ n software (IS)
                                                                  o

        Existen tres procesos A, B y C que est´ n listos para ejecutar en ese mismo
                                               a
        orden. El modelo que siguen estos tres procesos es el siguiente:

                                         Proc A          CPU (15ut.)

                                         Proc B           CPU (2ut.)    E/S (1ut.)   CPU (3ut.)

                                         Proc C           CPU (1ut.)    E/S (6ut.)   CPU (4ut.)


        Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de
                   e                   o      a



                              @ibaumo
        tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S
                              e
        est´ n siendo utilizados.
           a


1.3.        Hilos
 26. Modifica el programa que se ilustra en el enunciado del problema 15 de ma-
     nera que reciba dos n´ meros enteros como par´ metros de entrada y calcule
                            u                           a
     sus factoriales de forma concurrente utilizando dos hilos que se ejecutan en
     paralelo con el hilo principal. El hilo principal deber´ esperar a que terminen
                                                            a
     los otros dos hilos. Recuerda que para compilarlo se debe a˜ adir -lpthread a
                                                                   n
     la orden gcc.

 27. Modifica el programa resultado del problema 26 de manera que no est´ li-   e
     mitado a 2 el n´ mero de factoriales a calcular. Haz que se creen tantos hilos
                    u
     como par´ metros de entrada y que todos se ejecuten de forma concurrente.
               a
     El hilo principal debe esperar a que terminen el resto de hilos y, a medida
     que vayan terminando, muestre un mensaje que indique un identificador del
     hilo finalizado.

 28. Modifica el programa soluci´ n del problema 13 para que la escritura de ca-
                                   o
     da cadena la haga un hilo diferente que se ejecutan en paralelo con el hilo
     principal. El hilo principal debe esperar a que terminen los otros dos hilos.

                                                                   13

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7           18                     100 Ejercicios resueltos de Sistemas Operativos - UJI
29. El siguiente programa cuenta el n´ mero de veces que el car´ cter ’a’ o ’A’
                                       u                             a
    aparece en el fichero indicado como par´ metro de entrada. Modif´calo para
                                              a                          ı
                                    ´
    que ahora se cree un hilo y sea este el que ejecute la funci´ n cuenta.
                                                                o
     #include           unistd.h
     #include           stdlib.h
     #include           stdio.h
     #include           sys/types.h
     #include           sys/stat.h
     #include           fcntl.h

     #define MAXLON 1000

     void cuenta (char ∗nombre) {

         int pos, cont= 0, leidos;
         char cadena[MAXLON];
         int fd;

         fd= open (nombre, O RDONLY);
         while ((leidos= read (mf, cadena, MAXLON))!= 0)
           for (pos= 0; pos leidos; pos++)
             if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’))
               cont++;
         printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn, nombre, cont);
         close (fd);
     }

     int main (int argc, char ∗argv[]) {




                               @ibaumo
         if (argc!= 2) {
           printf (Indica el nombre de un fichero.n);
           exit(0);
         }
         cuenta (argv[1]);
         return 0;
     }


30. Modifica el programa resultado del problema 29 para que se creen tantos
    hilos como ficheros especificados como par´ metros de entrada, y que todos
                                                a
    los hilos creados se ejecuten de forma concurrente.

31. Modifica el programa resultado del problema 30 para que el resultado de la
    b´ squeda lo informe el hilo principal cuando hayan terminado el resto de
     u
    hilos. Haz uso del paso de par´ metros a un hilo para que cada hilo pueda
                                     a
    devolver el resultado de la b´ squeda al hilo principal.
                                 u

32. Modifica el programa soluci´ n del problema 30 para obtener el n´ mero de
                                 o                                     u
    espacios en blanco que hay en cada uno de los ficheros dados como par´ me-
                                                                           a
    tros. Inicialmente, se deben crear tantos procesos como ficheros especifica-
    dos. Cada proceso crear´ los hilos necesarios, que son los que realizar´ n la
                             a                                             a
    b´ squeda, atendiendo a la restricci´ n de que un hilo procesar´ como m´ xi-
      u                                 o                          a        a
    mo K caracteres, donde K es una constante predefinida. Todos los hilos y
    procesos se han de ejecutar de forma concurrente. Cada proceso esperar´ a a
    que terminen sus hilos y mostrar´ el total de espacios encontrados.
                                     a

                                                                    14

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        19     100 Ejercicios resueltos de Sistemas Operativos - UJI
Cap´tulo 2
   ı

Comunicaci´ n y Sincronizaci´ n
            o               o
de Procesos

2.1.         Tuber´as
                  ı
                                                            ´
 33. Se desea informar del tiempo invertido en ejecutar las ordenes ls | wc -l. Para
     ello se escribe el siguiente programa. Sin embargo, no informa de forma
     correcta. Modif´calo para que lo haga sin cambiar el n´ mero de procesos
                      ı                                        u



                              @ibaumo
     que se est´ n generando.
               a
         #include          stdio.h
         #include          stdlib.h
         #include          unistd.h
         #include          time.h
         #include          sys/types.h
         #include          sys/wait.h

         int main (int argc, char ∗argv[]){
           int tubo[2];
           time t ini, fin;
           pipe(tubo);
           if(fork()==0){
             if(fork()==0){
               dup2(tubo[1],STDOUT FILENO);
               close(tubo[0]);
               close(tubo[1]);
               execlp(ls,ls,NULL);
             }else{
               dup2(tubo[0],STDIN FILENO);
               close(tubo[0]);
               close(tubo[1]);
               execlp(wc,wc,-l,NULL);
             }
           }
           else{
             printf(Tiempo invertido: %ld segundosn, fin-ini);
           }
           return 0;
         }




                                                                   15

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        20   100 Ejercicios resueltos de Sistemas Operativos - UJI
34. Observa el siguiente fragmento de c´ digo que trata de realizar lo mismo que
                                            o
    si un usuario escribiera ls | sort en la l´nea de comandos de un sistema UNIX.
                                              ı
    Indica qu´ problemas se producen, por qu´ y c´ mo resolverlos.
              e                                    e o
     int tubo[2];
     pipe(tubo);
     if (fork()!=0) {
       dup2(tubo[1], STDIN FILENO);
       execlp(sort, sort, NULL);
       close(tubo[0]);
       close(tubo[1]);
     } else {
       dup2(tubo[0], STDOUT FILENO);
       close(tubo[1]);
       close(tubo[0]);
       execlp(ls, ls, NULL);
     }



35. Al ejecutar el siguiente programa, el proceso no termina. Explica por qu´ .
                                                                            e
    Da una soluci´ n que no cambie el n´ mero de procesos que se generan.
                  o                    u
     int main(int argc, char ∗argv[]) {
       int tubo[2];
       pipe(tubo);
       if (fork()==0) {
         if (fork()== 0) {
           dup2 (tubo[1], STDOUT FILENO);
           close(tubo[0]);




                               @ibaumo
           close(tubo[1]);
           execlp(ls, ls, NULL);
         } else {
           dup2 (tubo[0], STDIN FILENO);
           close(tubo[0]);
           close(tubo[1]);
           execlp(wc, wc, -l, NULL);
         }
       } else {
         wait(NULL);
         printf (Fin del proceson);
       }
     }



36. Describe todas las situaciones que se producen o podr´an producirse al eje-
                                                         ı
    cutar el siguiente programa:
     int main (int argc,char ∗ argv[]) {

         int tubo[2];
         FILE ∗fichero;
         char linea[MAX];

         pipe(tubo);

         if(!(fichero=fopen(argv[1],r))){
           printf(Error al abrir el fichero %sn,argv[1]);
           exit(2);
         }




                                                                    16

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        21   100 Ejercicios resueltos de Sistemas Operativos - UJI
while(fgets(linea,MAX,fichero))
           write(tubo[1],linea,strlen(linea));
         fclose(fichero);

         close (tubo[1]);
         dup2 (tubo[0],STDIN FILENO);
         close (tubo[0]);
         execlp(sort,sort,NULL);

         exit(0);
     }



37. Describe todas las situaciones que se producen o podr´an producirse al eje-
                                                         ı
    cutar el siguiente programa:
     int main(int argc, char ∗argv[]) {
       int tubo[2];
       pipe(tubo);
       if (fork()==0) {
         close(tubo[0]);
         dup2(tubo[1], STDOUT FILENO);
         close(tubo[1]);
         execlp(ls, ls, NULL);
       } else {
         dup2(tubo[0], STDIN FILENO);
         close(tubo[0]);
         close(tubo[1]);
         wait(NULL);
         execlp(wc, wc, -l, NULL);




                               @ibaumo
       }
       exit(0);
     }



                                                           ´
38. Escribe un programa que ejecute la siguiente l´nea de ordenes igual que lo
                                                   ı
    har´a un int´ rprete de comandos: paste fich1 fich2 | sort | nl  fich3. Debes
        ı        e
    considerar que fich1, fich2 y fich3 ser´ n par´ metros dados a tu programa en
                                         a     a
    la l´nea de comandos.
        ı

39. Escribe un programa que genere tres procesos en paralelo que colaboran para
    realizar las siguientes tareas:

               El primer proceso, utilizando la orden grep, encontrar´ las l´neas de un
                                                                      a      ı
               fichero (fich1) que contienen una palabra (ambos dados como par´ me- a
               tros en la l´nea de comandos) y las escribir´ en una tuber´a.
                           ı                               a             ı
               El segundo proceso, utilizando la orden grep, encontrar´ las l´neas de
                                                                          a    ı
               un fichero (fich2) que contienen la misma palabra (ambos dados como
               par´ metros en la l´nea de comandos) y las escribir´ en la misma tuber´a.
                  a               ı                               a                  ı
               El tercer proceso, utilizando la orden wc, leer´ de la tuber´a las l´neas
                                                              a             ı      ı
               producidas por los otros dos, las contar´ y escribir´ el resultado en un
                                                        a          a
               nuevo fichero (fich3) pasado como par´ metro en la l´nea de comandos.
                                                      a              ı

     As´, el programa se utilizar´ en la l´nea de comandos de la siguiente forma:
       ı                         a        ı

                                                                    17


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        22   100 Ejercicios resueltos de Sistemas Operativos - UJI
$ programa palabra fich1 fich2 fich3. La figura 2.1 muestra gr´ ficamente la
                                                               a
     comunicaci´ n requerida entre los procesos.
               o




                                Figura 2.1: Esquema de funcionamiento.

40. Escribe un programa que genere tres procesos en paralelo que colaboran para
    realizar las siguientes tareas:

               El primer proceso leer´ l´neas de un fichero de texto dado como par´ me-
                                       a ı                                          a
               tro y escribir´ alternativamente en dos tuber´as las l´neas pares e impa-
                             a                              ı        ı
               res del mismo.
               El segundo proceso, utilizando la orden grep, leer´ de la tuber´a que
                                                                    a           ı
               contiene las l´neas pares y seleccionar´ aquellas l´neas que contengan
                             ı                        a           ı
               una palabra dada como par´ metro en la l´nea de comandos. El resultado
                                          a             ı
               se almacenara en un fichero cuyo nombre estar´ formado por la palabra
                                                              a
               dada seguido de .txt.



                               @ibaumo
               El tercer proceso realiza una funci´ n similar sobre la tuber´a que con-
                                                    o                       ı
               tiene las l´neas impares, pero utilizando otra palabra tambi´ n dada co-
                          ı                                                 e
               mo par´ metro.
                       a

     La figura 2.2 muestra gr´ ficamente los procesos y c´ mo se comunican estos
                            a                          o
     cuando el programa se ejecuta con los siguientes par´ metros: $ programa
                                                          a
     fichero.txt uno dos




                                Figura 2.2: Esquema de funcionamiento.

41. Escribe un programa que genere los procesos necesarios para que colaboren
    en realizar las siguientes tareas:

               Tarea 1: leer l´neas de un fichero de texto dado como par´ metro de
                               ı                                            a
               entrada y escribir alternativamente en dos tuber´as (tuber´a 1 y tuber´a
                                                               ı         ı           ı
               2) las l´neas pares e impares del mismo.
                       ı

                                                                    18

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        23   100 Ejercicios resueltos de Sistemas Operativos - UJI
Tarea 2: utilizando el comando grep, leer de la tuber´a que contiene las
                                                                       ı
                  l´neas pares y seleccionar aquellas l´neas que contengan una palabra
                   ı                                   ı
                  dada como par´ metro en la l´nea de comandos. El resultado se enviar´ a
                                  a           ı                                        a
                  trav´ s de la tuber´a 3.
                      e              ı
                  Tarea 3: realizar una funci´ n similar a la tarea 2 pero sobre la tuber´a
                                             o                                           ı
                  que contiene las l´neas impares y utilizando otra palabra diferente tam-
                                    ı
                  bi´ n dada como par´ metro de entrada.
                    e                 a
                  Tarea 4: ejecutar el comando sort sobre la informaci´ n que se recoja
                                                                        o
                  por la tuber´a 3 de manera que se muestren de forma ordenada las l´neas
                              ı                                                     ı
                  recogidas.

        Observa la siguiente figura 2.3. En ella se representa de forma gr´ fica una
                                                                             a
        propuesta de los procesos que se deben generar y de c´ mo se comunican es-
                                                              o
        tos cuando el programa se ejecute con los siguientes par´ metros: $ programa
                                                                a
        fichero.txt uno dos. Antes de comenzar a escribir la soluci´ n, determina si
                                                                    o
        est´ s de acuerdo o no con el esquema de funcionamiento propuesto. Si no lo
           a
        est´ s explica porqu´ .
           a                e




                              @ibaumo
                                   Figura 2.3: Esquema de funcionamiento.



2.2.        Sem´ foros
               a
 42. Dados los siguientes procesos y sus respectivas secuencias de c´ digo, indica
                                                                       o
     si existir´a o no situaci´ n de interbloqueo y explica por qu´ . En cualquier
               ı              o                                     e
     caso, indica tambi´ n la salida por pantalla y el valor final de los sem´ foros.
                         e                                                  a
     Sup´ n que inicialmente todos los sem´ foros tienen valor cero.
         o                                   a

          Proceso 1                              Proceso 2                   Proceso 3
          ---------                              ---------                   ---------
          printf(3);                           sem_wait(s1);              sem_wait(s2);
          sem_post(s3);                         printf(1);                sem_wait(s4);
          printf(4);                           sem_wait(s3);              printf(2);
          sem_post(s2);                         sem_post(s4);              printf(5);
          sem_post(s1);                         sem_wait(s3);              sem_post(s3);



                                                                   19

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        24                    100 Ejercicios resueltos de Sistemas Operativos - UJI
43. Considera que los siguientes fragmentos de c´ digo se ejecutan en paralelo:
                                                o

             C´digo A:
              o                                                     C´digo B:
                                                                     o
             ---------                                              ---------
                printf(A1);                                          printf(B1);
               sem_post(s1);                                         sem_wait(s1);
               sem_wait(s2);                                         printf(B2);
               printf(A2);                                          sem_post(s3);
               sem_wait(s2);                                         sem_wait(s3);
               sem_post(s1);                                         printf(B3);
               printf(A3);                                          sem_post(s2);
                                                                      sem_wait(s1);
                                                                      sem_post(s2);
                                                                      printf(B4);


     Sabiendo que todos los sem´ foros est´ n inicializados a 0, indica todas las
                                 a        a
     posibles salidas que puede proporcionar su ejecuci´ n y si se produce o no
                                                         o
     interbloqueo para cada una de ellas.

44. Modifica el programa resultado del problema 31 para que, utilizando una
    variable global a la cual acceden todos los hilos (ll´ mala cuenta blancos),
                                                         a
    estos acumulen el total de blancos encontrados. Utiliza un sem´ foro para
                                                                      a
    asegurar que los accesos a dicha variable se realizan de forma adecuada.
    Haz que el programa principal informe tambi´ n del resultado.
                                                 e

45. Escribe un programa que ejecute tres hilos en paralelo a los que llamaremos



                               @ibaumo
    A, B y C. El hilo A consta de tres bloques de c´ digo (a1, a2 y a3), el hilo B
                                                     o
    de otros cuatro (b1, b2, b3 y b4) y el C de 3 (c1, c2 y c3). Haz que el c´ digo
                                                                             o
    de cada uno de estos bloques consista en repetir cinco veces los siguientes
    pasos: escribir un mensaje que lo identifique y realizar un retardo aleatorio.
    Ejecuta el programa para comprobar que los hilos A, B y C se ejecutan en
    paralelo y que sus bloques de c´ digo pueden alternarse de varias formas
                                      o
    distintas. Ahora, modifica el programa anterior para que los tres hilos se
    sincronicen de la siguiente forma:

               c1 no debe comenzar hasta que acabe a1
               a2 no debe comenzar hasta que acabe b1
               c2 no debe comenzar hasta que acabe b2
               b3 no debe comenzar hasta que acabe a2
               a3 no debe comenzar hasta que acabe c2
                                 ´
               b4 debe acabar el ultimo

46. Se crean tres hilos de manera que uno ejecuta escribirA, otro escribirB y el
    tercero escribirC. Introduce los sem´ foros oportunos para que la salida sea
                                        a
    ABCABCABCABCABCABC.
     #include stdio.h
     #include stdlib.h
     #include time.h


                                                                    20

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7            25        100 Ejercicios resueltos de Sistemas Operativos - UJI
#include unistd.h
     #include pthread.h

     #define MAX 6

     void ∗escribirA (void ∗nada){
       int num;
       for(num=0;numMAX;num++){
         printf(A);
         fflush(NULL);
         sleep(random() %3);
       }
       pthread exit(NULL);
     }

     void ∗escribirB (void ∗nada){
       int num;
       for(num=0;numMAX;num++){
         printf(B);
         fflush(NULL);
         sleep(random() %2);
       }
       pthread exit(NULL);
     }

     void ∗escribirC (void ∗nada){
       int num;
       for(num=0;numMAX;num++){
         printf(C);
         fflush(NULL);




                               @ibaumo
         sleep(random() %2);
       }
       pthread exit(NULL);
     }

     int main (int argc, char ∗argv[]) {

         pthread t th1, th2, th3;
         srandom(time(NULL));
         pthread create(th1, NULL, escribirA, NULL);
         pthread create(th2, NULL, escribirB, NULL);
         pthread create(th3, NULL, escribirC, NULL);
         pthread join(th1, NULL);
         pthread join(th2, NULL);
         pthread join(th3, NULL);
         return 0;
     }


47. Observa el siguiente fragmento de c´ digo donde los sem´ foros sem1 y sem2
                                         o                     a
    est´ n inicializados a cero, un hilo ejecuta la funci´ n incrementa y otro la
       a                                                 o
    funci´ n decrementa. Describe los valores que, durante la ejecuci´ n, puede
          o                                                            o
    adoptar la variable num as´ como las posibles situaciones de interbloqueo
                                 ı
    que pudieran darse.




                                                                    21


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        26   100 Ejercicios resueltos de Sistemas Operativos - UJI
int num=10;

     void ∗ incrementa(void ∗nada) {
       int i;
       for (i=0;i3;i++){
         sem wait(sem1);
         num++;
         printf(Inc. N´ mero = %dn,num);
                       u
         sem post(sem1);
       }
       sem post(sem2);
       sleep(random() %3);
       sem wait(sem2);
       pthread exit(NULL);
     }
     void ∗ decrementa(void ∗nada){
       int i;
       for (i=0;i3;i++){
         sem post(sem1);
         sleep(random() %3);
         sem wait(sem2);
         num--;
         printf(Dec. N´ mero = %dn,num);
                        u
         sem post(sem2);
         sem wait(sem1);
       }
       sem wait(sem1);
       pthread exit(NULL);
     }




                               @ibaumo
48. Se crean dos hilos de manera que uno ejecuta escribirA y el otro escribirB.
    Introduce los sem´ foros oportunos para que la salida sea BABABABABA.
                      a
    No olvides indicar los valores iniciales de los sem´ foros que utilices.
                                                       a
     void ∗escribirA (void ∗p) {
       int i;
       for (i= 0; i 5; i++) {
         printf (A);
         fflush(NULL);
         sleep(random() %2);
       }
       pthread exit(NULL);
     }

     void ∗escribirB (void ∗p) {
       int i;
       for (i= 0;i 5; i++) {
         printf (B);
         fflush(NULL);
         sleep(random() %2);
       }
       pthread exit(NULL);
     }



49. Dado el siguiente c´ digo indica si existe o no interbloqueo. En el caso de
                          o
    existir, indica claramente para cada hilo en qu´ l´nea de c´ digo se queda
                                                       e ı        o
    bloqueado y en qu´ iteraci´ n del bucle ocurre (valores de las variables i, j,
                        e      o
    k). Observa los valores de inicializaci´ n de los sem´ foros.
                                           o              a

                                                                    22


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        27   100 Ejercicios resueltos de Sistemas Operativos - UJI
sem t s1, s2, s3;

     void ∗escribirA (void ∗p){
       int i;
       srandom (pthread self ());
       for (i= 0; i MAX; i++){
         printf (A);
         sem post (s2);
         sem wait (s1);
         fflush (NULL);
         sleep (random() %3);
       }
       pthread exit (NULL);
     }

     void ∗escribirB (void ∗p){
       int j;
       srandom (pthread self ());
       for (j= 0; j MAX; j++){
         sem wait (s2);
         printf (B);
         sem post (s3);
         sem wait (s2);
         fflush (NULL);
         sleep (random() %2);
       }
       pthread exit (NULL);
     }

     void ∗escribirC (void ∗p){




                               @ibaumo
       int k;
       srandom (pthread self ());
       for (k= 0; k MAX; k++){
         sem wait (s3);
         printf (C);
         sem post (s1);
         sem wait (s3);
         fflush (NULL);
         sleep (random() %2);
       }
       pthread exit (NULL);
     }

     int main (int argc, char ∗argv[]) {
       pthread t th1, th2, th3;
       sem init (s1, 0, 1);
       sem init (s2, 0, 1);
       sem init (s3, 0, 0);
       pthread create (th1, NULL, escribirA, NULL);
       pthread create (th2, NULL, escribirB, NULL);
       pthread create (th3, NULL, escribirC, NULL);
       pthread join (th1, NULL);
       pthread join (th2, NULL);
       pthread join (th3, NULL);
       return 0;
     }


50. Considera el siguiente trozo de c´ digo del problema productor-consumidor:
                                     o
     #include stdio.h
     #include stdlib.h
     #include semaphore.h


                                                                    23


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        28   100 Ejercicios resueltos de Sistemas Operativos - UJI
#include pthread.h
     #include unistd.h
     #include stdbool.h

     #define MAX 10
     #define FIN -1

     int buffer[MAX];
     sem t huecos, elementos;

     int generar dato (void) { return random() %256;}
     int numero aleatorio(void) { return random() %100;}

     void ∗productor (void ∗p) {

         int pos productor= 0;
         int num, dato, n;

         n= numero aleatorio();
         printf (Productor con %d datosn, n);
         for(num= 0; num n; num++) {
           dato= generar dato();
           sem wait (huecos);
           buffer[pos productor]= dato;
           pos productor= (pos productor+ 1) %MAX;
           sem post (elementos);
         }
         buffer[pos productor]= FIN;
         pthread exit (NULL);
     }




                               @ibaumo
     void ∗consumidor(void ∗p){

         int pos consumidor, dato;
         bool continuar= true;

         while (continuar) {
           sem wait (elementos);
           dato= buffer[pos consumidor];
           pos consumidor= (pos consumidor+1) %MAX;
           if (dato== FIN)
             continuar= false;
           sem post (huecos);
           printf (Numero aleatorio: %dn, dato);
         }
         pthread exit (NULL);
     }

     Este c´ digo contiene errores y est´ incompleto. Corrige y completa. Haz que
            o                           a
     el hilo consumidor muestre en pantalla todos los datos producidos por el hilo
     productor.
51. Realiza las modificaciones oportunas al c´ digo resultado del problema 50
                                              o
    para que en lugar de un hilo productor hayan tres que se ejecuten en parale-
    lo. El consumidor terminar´ cuando haya consumido todos los datos produ-
                               a
    cidos.
52. Escribe un programa que ejecute dos hilos en paralelo para realizar las si-
    guientes tareas:

                                                                    24


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        29   100 Ejercicios resueltos de Sistemas Operativos - UJI
El primer hilo calcular´ los n´ meros primos que hay entre dos n´ meros
                                      a      u                                 u
               que el programa recibe como par´ metros. Para enviar estos datos al
                                                   a
               segundo hilo, los almacenar´ en un buffer intermedio de 5 elementos
                                             a
               de capacidad.
               El segundo hilo tomar´ los datos que aparezcan en el buffer intermedio
                                     a
               y calcular´ la suma de los d´gitos de cada n´ mero. Para cada n´ mero
                         a                 ı                u                   u
               primo se mostrar´ en la salida est´ ndar una l´nea que contendr´ dicho
                                a                a           ı                 a
               n´ mero y la suma de sus d´gitos.
                u                        ı

     Deber´ s utilizar sem´ foros para que los dos hilos se sincronicen en el acceso
           a              a
     al buffer intermedio. Estas son las funciones para comprobar si un n´ mero
                                                                              u
     es primo y para calcular la suma de los d´gitos de un n´ mero.
                                                ı              u
     /∗ Devuelve la suma de los d´gitos del n´mero dado ∗/
                                 ı           u
     int suma digitos (int numero) {

         int suma= 0;

         while (numero 0) {
           suma+= numero %10;
           numero/= 10;
         }
         return suma;
     }




                               @ibaumo
     /∗ Indica si el n´mero dado es primo ∗/
                      u
     bool es primo (int numero) {

         int divisor;

         for (divisor= 2; divisor= sqrt(numero); divisor++)
           if (numero %divisor== 0)
             return false;

         return true;
     }



53. Escribe un programa que realice una simulaci´ n de la evoluci´ n del estado
                                                     o               o
    de las reservas en una aula de libre acceso. Para simplificar, sup´ n que el aula
                                                                     o
    tiene s´ lo un ordenador que se puede reservar en per´odos de 1 hora, desde
           o                                                ı
    las 9:00 hasta las 21:00. 25 alumnos pueden reservar per´odos individuales
                                                                ı
    de 1 hora, cancelar reservas y consultar el estado de las reservas.
     La simulaci´ n debe consistir en que cada alumno realice cuatro operacio-
                  o
     nes, cada una de las cuales podr´ ser una reserva, cancelaci´ n o consulta. La
                                       a                           o
     elecci´ n de la operaci´ n ser´ aleatoria, pero con mayor probabilidad para la
           o                o      a
     realizaci´ n de reservas (50 %) que para la realizaci´ n de consultas y cancela-
              o                                           o
     ciones (25 % cada una). Cuando la operaci´ n a realizar sea una reserva, debe
                                                  o
     elegirse aleatoriamente la hora que el alumno va a reservar.
     El programa debe implementar un hilo principal que lanza 25 hilos en parale-
     lo, uno por cada alumno. Mediante el empleo de sem´ foros debe garantizarse
                                                        a

                                                                    25

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        30   100 Ejercicios resueltos de Sistemas Operativos - UJI
que los accesos a la tabla de reservas sean correctos. En concreto, cuando se
realice una reserva o cancelaci´ n no puede realizarse ninguna otra operaci´ n
                                o                                          o
en paralelo sobre la tabla, pero una consulta puede simultanear su acceso a
la tabla con otras consultas.
En la implementaci´ n de la consulta de la tabla, muestra por pantalla el esta-
                    o
do de cada per´odo de una hora en una l´nea distinta. Para realizar una reser-
               ı                          ı
va, comprueba que el per´odo que se solicita reservar est´ libre. Al realizar
                           ı                                e
una cancelaci´ n, deben quedar libres todas las horas que tuviese reservadas
              o
el estudiante que la solicita. Si ese estudiante no tuviese ninguna reserva se
debe mostrar un mensaje de error.
Como todas las operaciones est´ n controladas por sem´ foros, escribe mensa-
                                 a                        a
jes que indiquen el estado de las operaciones diferenciando cu´ ndo se solicita
                                                                 a
realizar una acci´ n (a´ n no se tiene autorizaci´ n), y cu´ ndo se realiza efec-
                 o     u                         o          a
tivamente (ya se tiene autorizaci´ n). As´, se puede seguir la evoluci´ n de las
                                   o      ı                             o
operaciones y los efectos que producen en el estado de la tabla de reservas.
A continuaci´ n tienes un ejemplo del tipo de traza que se espera obtener.
             o

Solicitud de reserva de al012: 9-10
Reserva de al012: 9-10
Solicitud de consulta de al004
Solicitud de cancelaci´n de al006
                       o




                               @ibaumo
Solicitud de reserva de al000: 15-16
Solicitud de consulta de al019
Consulta de al019: 9-10 = al012
Consulta de al019: 10-11 = LIBRE
Consulta de al019: 11-12 = LIBRE
Consulta de al019: 12-13 = LIBRE
Consulta de al019: 13-14 = LIBRE
Consulta de al019: 14-15 = LIBRE
Consulta de al019: 15-16 = LIBRE
Consulta de al019: 16-17 = LIBRE
Consulta de al019: 17-18 = LIBRE
Consulta de al004: 9-10 = al012
Consulta de al004: 10-11 = LIBRE
Consulta de al004: 11-12 = LIBRE
Consulta de al004: 12-13 = LIBRE
Consulta de al004: 13-14 = LIBRE
Consulta de al004: 14-15 = LIBRE
Consulta de al004: 15-16 = LIBRE
Consulta de al004: 16-17 = LIBRE
Consulta de al004: 17-18 = LIBRE
Consulta de al004: 18-19 = LIBRE
Consulta de al004: 19-20 = LIBRE
Consulta de al004: 20-21 = LIBRE
Consulta de al019: 18-19 = LIBRE
Consulta de al019: 19-20 = LIBRE
Consulta de al019: 20-21 = LIBRE
Denegada cancelaci´n de al006: No tiene reservas
                  o
Reserva de al000: 15-16


                                                            26

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   31   100 Ejercicios resueltos de Sistemas Operativos - UJI
Solicitud de reserva de al010: 9-10
     Denegada reserva de al010: 9-10 est´ ocupada
                                        a
     Solicitud de cancelaci´n de al012
                           o
     Cancelaci´n de al012: 9-10
              o
     ...


                                o                     ı              ´
54. Un puente es estrecho y s´ lo permite pasar veh´culos en un unico sentido
    al mismo tiempo. Si pasa un coche en un sentido y hay coches en el mismo
    sentido que quieren pasar, entonces estos tienen prioridad frente a los del otro
    sentido (si hubiera alguno esperando para entrar en el puente). No hay l´mite
                                                                              ı
    al n´ mero de veh´culos que pueden haber en el puente al mismo tiempo.
        u             ı
     Simula el sistema suponiendo que los coches son hilos y el puente el recurso
     compartido. Utiliza sem´ foros para garantizar que se cumplen las condicio-
                               a
     nes de acceso al puente. Cada hilo debe mostrar por pantalla cu´ ndo entra
                                                                      a
     en el puente y cu´ ndo lo abandona.Se generar´ n un total de 100 veh´culos,
                        a                             a                    ı
     50 en un sentido y 50 en el otro. Tras un tiempo de espera al azar (utili-
     zar sleep(random() %20) o algo similar) los veh´culos intentan entrar en el
                                                         ı
                                                   ´
     puente y, si lo consiguen, permanecer´ n en el durante un segundo (sleep(1))
                                             a
     antes de abandonarlo. Se apreciar´ m´ s el comportamiento del sistema si se
                                         a a
     alterna la creaci´ n de hilos en un sentido u otro.
                      o




                               @ibaumo



                                                                    27


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        32   100 Ejercicios resueltos de Sistemas Operativos - UJI
Cap´tulo 3
   ı

Gesti´ n de Archivos y Directorios
     o

3.1.         Sistemas de Archivos
 55. Disponemos de un disco duro de 20 GB de capacidad. Hay establecida sobre
     ´      ´
     el una unica partici´ n que contiene un sistema de ficheros del tipo FAT32 en
                         o
     el que cada agrupamiento (cluster) consta de 16 sectores de 512 bytes cada
     uno. ¿Cu´ ntos sectores del disco se necesitar´ n para almacenar cada copia
              a                                     a
     de la FAT? Razona tu respuesta.




                              @ibaumo
 56. La polic´a ha arrestado al sospechoso de un delito. Al analizar el contenido
              ı
     de su ordenador piensan que pueden inculparle pues el contenido del mismo
     es el siguiente:

                                                N´ m de bloque de datos
                                                 u                           Contenido
                                                          10                     he
                                                          11                    sido
                                                          12                     yo
                                                          13                     no
                                                          14                   sigan
                                                          15                 buscando

         Como experto inform´ tico, pides consultar el contenido de la FAT, que es el
                            a
         siguiente:

                                              N´ m de entrada en la FAT
                                               u                             Contenido
                                                         10                     11
                                                         11                    EOF
                                                         12                     13
                                                         13                     10
                                                         14                     15
                                                         15                     12

         ¿Apoyar´as la opini´ n de la polic´a? Razona tu respuesta.
                ı           o              ı

                                                                   29
 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        33               100 Ejercicios resueltos de Sistemas Operativos - UJI
57. Tenemos un sistema de ficheros tipo FAT sobre el que hay almacenado un
    fichero de 160 Kbytes. Sabemos que para dicho fichero se emplean 10 en-
    tradas de la FAT y que cada sector del disco contiene 512 bytes. ¿Cu´ ntos
                                                                        a
    sectores como m´nimo forman cada bloque o agrupamiento en dicho siste-
                    ı
    ma? Razona tu respuesta.

58. Se dispone de una partici´ n de disco con sistema de ficheros basado en
                                 o
    FAT16. Si el tama˜ o de bloque es de 1KB, ¿cu´ ntos KB de dicha partici´ n
                       n                           a                          o
    podr´ n direccionarse como m´ ximo? Si la partici´ n resulta tener un tama˜ o
         a                           a               o                        n
    de 2GB, ¿qu´ tama˜ o deber´a como m´nimo tener el bloque para poder di-
                 e       n         ı      ı
    reccionar la partici´ n por completo?
                        o

59. Se dispone de una partici´ n de disco con sistema de ficheros basado en
                                 o
    FAT16. A la hora de ponerle formato el usuario especifica que los bloques
    sean de tama˜ o 4Kbytes ¿Cu´ ntos Kbytes te´ ricamente podr´ n direccionar-
                 n                 a              o               a
    se como m´ ximo? Si la partici´ n resulta tener un tama˜ o de 8Gbytes, ¿con-
               a                     o                     n
    sideras adecuado el tama˜ o de bloque escogido por el usuario? Justifica la
                               n
    respuesta. En caso de que no est´ s de acuerdo prop´ n un tama˜ o de bloque
                                       e                 o          n
    e indica en cu´ ntos de esos bloques se almacena la FAT.
                  a

60. Para una partici´ n de 8GB y tama˜ o de bloque de 1 KB,
                    o                n




                               @ibaumo
               Si se utiliza un sistema de ficheros basado en FAT16, ¿qu´ cantidad de
                                                                       e
               espacio en disco queda inutilizable?
               Si se utiliza un sistema de ficheros basado en nodos-i, donde cada nodo-
               i consta de dos ´ndices directos, dos indirectos simples y dos indirectos
                                ı
               dobles, y para referenciar un bloque se utilizan 128 bits, ¿qu´ cantidad
                                                                             e
               de datos de un fichero que en concreto ocupa 131 KB puede ser irrecu-
               perable en el caso de que un bloque de la partici´ n resultara ilegible?
                                                                   o
               Analiza todos los casos posibles.

61. Considera un sistema de ficheros basado en nodos-i, en el que cada nodo-i
    contiene cinco ´ndices directos, tres indirectos simples, dos indirectos dobles
                   ı
    y uno indirecto triple. Si el tama˜ o de un bloque de datos es de 2 Kbytes y
                                       n
    para referenciar a un bloque se utilizan 64 bits, ¿cu´ ntos bloques de disco
                                                           a
    almacenar´ n enlaces para un fichero que contiene 1548 Kbytes de datos?
              a
    Razona tu respuesta.

62. Sea una partici´ n de disco donde el tama˜ o de bloque es de 4KB. Se utiliza
                   o                          n
    un sistema de ficheros basado en nodos-i, donde cada nodo-i consta de dos
    ´ndices directos, dos indirectos simples y uno indirecto doble. Si para refe-
    ı
    renciar a un bloque se utilizan 32 bits, ¿cu´ l es el n´ mero de bloques que
                                                 a         u
    contendr´ n enlaces si el fichero ocupa el m´ ximo tama˜ o posible?
             a                                  a            n

                                                                    30

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        34   100 Ejercicios resueltos de Sistemas Operativos - UJI
3.2.        Archivos y Directorios
 63. La siguiente funci´ n muestra el nombre de todas las entradas del directorio
                       o
     que se le pasa como par´ metro:
                            a
        void listado(char nomdir[]) {
          DIR    ∗d;
          struct dirent ∗entrada;
          char   ∗ruta;

            d= opendir(nomdir);
            if (d== NULL)
              printf(Error al abrir el directorion);
            else {
              entrada= readdir(d);
              while (entrada!= NULL) {
                ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2);
                sprintf(ruta, %s/ %s, nomdir, entrada-d name);
                printf( %sn, ruta);
                free(ruta);
                entrada= readdir(d);
              }
              closedir(d);
            }
        }

                            ´
        Modif´cala para que unicamente muestre aquellas entradas que se correspon-
              ı
        dan con enlaces simb´ licos a directorios.
                             o




                              @ibaumo
 64. La siguiente funci´ n muestra el nombre de todas las entradas del directorio
                       o
     que se le pasa como par´ metro:
                            a

        void listado(char nomdir[]) {
          DIR    ∗d;
          struct dirent ∗entrada;
          char   ∗ruta;

            d= opendir(nomdir);
            if (d== NULL)
              printf(Error al abrir el directorion);
            else {
              entrada= readdir(d);
              while (entrada!= NULL) {
                ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2);
                sprintf(ruta, %s/ %s, nomdir, entrada-d name);
                printf( %sn, ruta);
                free(ruta);
                entrada= readdir(d);
              }
              closedir(d);
            }
        }

        Modif´cala para que por cada fichero regular que haya en el directorio se
              ı
        cree un archivo zip en el directorio /tmp y se muestre la diferencia de espacio
        entre el archivo original y el nuevo archivo zip. Crea el archivo zip con la
        orden zip ruta.zip ruta.


                                                                   31

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        35   100 Ejercicios resueltos de Sistemas Operativos - UJI
65. Escribe un programa que dado un directorio como argumento de entrada
    elimine los ficheros, enlaces y directorios (s´ lo los vac´os) que hubiesen en
                                                  o          ı
    ´
    el. El programa debe informar de si el directorio dado como par´ metro existe
                                                                    a
    as´ como de cada uno de los elementos eliminados. No hagas un recorrido
      ı
                  ´
    recursivo del arbol de directorios.

66. Escribe un programa que borre una serie de nombres de ficheros y/o direc-
    torios recibidos como par´ metros. Adem´ s, el programa debe mostrar para
                             a             a
    cada par´ metro dado:
             a

               si se trata de un fichero regular, un enlace simb´ lico, un directorio, o
                                                               o
               bien si el nombre dado no es v´ lido
                                              a
               si dicho nombre pudo borrarse correctamente, as´ como el n´ mero de
                                                                   ı           u
               bloques de disco que ser´ n liberados en tal caso. Ten en cuenta que, en
                                         a
               el caso de ficheros regulares, los bloques de disco s´ lo ser´ n liberados
                                                                     o     a
                               ´
               si se trata del ultimo enlace f´sico sobre el fichero.
                                              ı

67. Escribe un programa que, a partir de un directorio dado como par´ metro,
                                                                          a
    informe de los ficheros regulares que encuentre a partir de dicho directorio
                         ´
    (deber´ recorrer el arbol de directorios a partir de dicho directorio) tales
           a
    que pertenezcan al usuario que ejecuta el programa, y se hayan accedido
    desde una hora antes del comienzo de la ejecuci´ n del programa. Durante el
                                                     o



                               @ibaumo
    recorrido recursivo del directorio dado, se deben ignorar aquellos directorios
    que no puedan ser abiertos por no tener los permisos necesarios.

68. Escribe un programa que calcule la suma de los bytes ocupados por todos
    los ficheros y directorios que est´ n contenidos a partir de un directorio dado
                                     e
    como par´ metro. ¿Qu´ ocurre cuando hay dos enlaces duros que hacen refe-
               a           e
    rencia al mismo fichero? Haz que en estos casos el espacio ocupado se con-
    sidere s´ lo una vez. Ten en cuenta que la estructura stat contiene el n´ mero
            o                                                               u
    de nodo-i asignado al fichero.

69. Escribe un programa que reciba como argumentos un fichero regular y un di-
    rectorio, y cambie por enlaces simb´ licos al fichero regular todos los enlaces
                                       o
                      ´
    duros referidos a el que encuentre a partir del directorio dado. Para simpli-
    ficar, considera que tanto el fichero como el directorio se pasan al programa
    como caminos absolutos que no contienen el nombre ., ni el nombre .., ni
    ning´ n enlace simb´ lico.
         u              o

70. Un reproductor multimedia recorre de forma recursiva el directorio /media
    (y sus subdirectorios) a la b´ squeda de ficheros con extensi´ n jpeg, avi y
                                  u                                o
    mp3. En la ruta /resultado hay tres carpetas de nombres jpeg, avi y mp3. Por
    cada fichero regular que encuentra con la extensi´ n adecuada en el proceso
                                                       o
    de b´ squeda, crea un enlace simb´ lico en la carpeta correspondiente a la ex-
        u                             o
    tensi´ n del archivo. Por ejemplo, si encuentra un fichero con extensi´ n avi
         o                                                                 o

                                                                    32

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        36   100 Ejercicios resueltos de Sistemas Operativos - UJI
crea el enlace simb´ lico a dicho fichero en el directorio /resultado/avi. Es-
                   o
cribe un programa en C que funcione de acuerdo al enunciado del problema.
                                                           ´
Adem´ s, haz que no haya que crear el enlace al archivo si este ya existe.
      a




                               @ibaumo



                                                            33

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   37   100 Ejercicios resueltos de Sistemas Operativos - UJI
Cap´tulo 4
   ı

Gesti´ n de Memoria
     o

4.1.         Paginaci´ n
                     o
 71. Considera un sistema de paginaci´ n en el que se puede direccionar como
                                         o
     m´ ximo 1 Gbyte de memoria, el tama˜ o de p´ gina es de 16 Kbytes y cada
       a                                     n       a
     byte se direcciona independientemente ¿Cu´ ntas p´ ginas podr´ tener asig-
                                                   a       a          a
     nadas como m´ ximo un proceso en este sistema? Si empleamos una tabla
                     a
     de p´ ginas con dos niveles, en el que la tabla de primer nivel contiene 1024
         a




                              @ibaumo
     entradas, ¿cu´ ntas tablas de segundo nivel son necesarias para un proceso
                   a
     que requiere 6401 p´ ginas? Razona tu respuesta.
                          a
 72. Considera un sistema de paginaci´ n en el que las direcciones l´ gicas son
                                        o                               o
     de 22 bits y el tama˜ o de p´ gina es de 2 Kbytes. Sabiendo que cada by-
                          n       a
     te se direcciona independientemente, calcula el ahorro de memoria que ob-
     tendr´amos para representar la tabla de p´ ginas de un proceso que est´ utili-
           ı                                  a                              a
     zando 90 Kbytes de memoria, cuando empleamos una tabla de p´ ginas con
                                                                        a
     dos niveles en lugar de tener una tabla de un solo nivel. En el sistema con
     dos niveles, debes considerar que se emplean 5 bits de la direcci´ n para el
                                                                         o
     segundo nivel. Adem´ s, cada entrada de las tablas de p´ ginas precisa 8 bytes.
                          a                                 a
     Razona la respuesta.
 73. Considera un sistema de paginaci´ n en el que las direcciones l´ gicas son de
                                        o                             o
     20 bits y el tama˜ o de p´ gina de 4 Kbytes. Sabiendo que cada byte se direc-
                      n       a
     ciona independientemente, calcula el ahorro de memoria que obtendr´amos  ı
     para representar la tabla de p´ ginas de un proceso que est´ utilizando 192
                                     a                             a
     Kbytes de memoria, cuando empleamos un tabla de p´ ginas con dos niveles
                                                             a
     en lugar de tener una tabla de un solo nivel. En el sistema con dos niveles
     debes considerar que se emplea el mismo n´ mero de bits de la direcci´ n para
                                                 u                          o
     cada nivel. Cada entrada de las tablas de p´ ginas precisa 16 bytes. Razona tu
                                                a
     respuesta.
 74. Considera un sistema de paginaci´ n en el que las direcciones l´ gicas son de
                                        o                            o
     22 bits y el tama˜ o de p´ gina de 2 Kbytes, y que cada byte se direcciona in-
                      n       a

                                                                   35
 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        38   100 Ejercicios resueltos de Sistemas Operativos - UJI
dependientemente ¿Cu´ ntas p´ ginas podr´ tener asignadas como m´ ximo un
                               a      a           a                       a
        proceso en este sistema? Si empleamos una tabla de p´ ginas de dos niveles,
                                                             a
                                                    ´
        en la que la tabla de primer nivel contiene unicamente 8 entradas, ¿cu´ ntas
                                                                              a
        tablas de segundo nivel son necesarias para un proceso que requiere 1000
        p´ ginas? Razona la respuesta.
         a

 75. Lee las siguientes afirmaciones y razona si est´ s de acuerdo o no. Pon un
                                                   a
     ejemplo que apoye tu respuesta.

                  En un sistema de paginaci´ n, utilizar una tabla de p´ ginas de dos nive-
                                             o                         a
                  les suele producir un ahorro en el consumo de memoria en comparaci´ n  o
                  con el uso de una tabla de p´ ginas de un nivel.
                                               a
                  En un sistema de paginaci´ n, el n´ mero de p´ ginas que como m´ ximo
                                            o       u          a                 a
                  se le puede asignar a un proceso es mayor en el caso de utilizar una
                                                                                   ´
                  tabla de p´ ginas de dos niveles que en el caso de utilizar una unica
                             a
                  tabla de p´ ginas.
                            a

 76. Considera un sistema de paginaci´ n en donde se puede puede direccionar
                                        o
     un m´ ximo de 1GB y el tama˜ o de p´ gina es de 32KB. Sabiendo que cada
           a                       n       a
     palabra de 16 bits se direcciona independientemente, calcula el ahorro de
     memoria que obtendriamos de representar la tabla de p´ ginas de un proce-
                                                              a
     so que est´ utilizando 90MB de memoria, cuando empleamos una tabla de
                a




                              @ibaumo
     p´ ginas de dos niveles en lugar de tener una tabla de un solo nivel. En el
      a
     sistema de dos niveles, debes considerar que se emplear´ el mismo n´ mero
                                                               a             u
     de bits para cada nivel. Adem´ s, cada entrada en la tabla de p´ ginas precisa
                                   a                                a
     de 16 bytes. Razona la respuesta.

 77. Se considera un sistema de paginaci´ n en donde se puede direccionar un
                                            o
     m´ ximo de 1GB y el tama˜ o de p´ gina es de 32KB. Sabiendo que el tama˜ o
       a                         n     a                                        n
     de la palabra es de 64 bits y que cada palabra se direcciona independiente-
     mente, calcula el ahorro de memoria que obtendr´amos de representar la ta-
                                                        ı
     bla de p´ ginas de un proceso que est´ utilizando 256 MB de memoria cuando
             a                            a
     se emplea una tabla de p´ ginas de dos niveles en lugar de tener una tabla de
                               a
     un solo nivel. En el de dos niveles, debes considerar que se emplear´ el mis-
                                                                         a
     mo n´ mero de bits para cada nivel. Adem´ s cada entrada de p´ ginas precisa
          u                                      a                  a
     de 8 bytes. Razona la respuesta.


4.2.        Pol´ticas de Reemplazo
               ı
   Para realizar los siguientes ejercicios ten en cuenta que:

        Inicialmente los marcos est´ n libres.
                                   a

        La pol´tica de reemplazo s´ lo se utiliza a partir del momento en que no hayan
              ı                   o
        marcos libres.

                                                                   36

 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        39   100 Ejercicios resueltos de Sistemas Operativos - UJI
78. Considera un sistema de paginaci´ n bajo demanda en el que un proceso que
                                      o
    tiene asignados 3 marcos de p´ gina genera la siguiente secuencia de referen-
                                 a
    cias a p´ ginas:
            a
                      2,3,1,2,4,5,2,3,1,5,6,1
     Indica qu´ accesos producir´an un fallo de p´ gina cuando se utilizan las
                e                   ı                a
     pol´ticas de reemplazo local FIFO y LRU. Sabemos que este proceso se va a
        ı
     ejecutar muy a menudo en el sistema y nos interesa tener el mejor sistema de
                      ´
     paginaci´ n para el. ¿Valdr´a la pena aumentar el n´ mero de marcos de p´ gi-
              o                 ı                       u                     a
     na asignados al proceso hasta 4 para alguna de estas dos pol´ticas? Indica el
                                                                  ı
     n´ mero de fallos de p´ gina que se producir´an en esta nueva situaci´ n para
      u                     a                    ı                        o
     cada algoritmo.

79. Considera un sistema de paginaci´ n bajo demanda en el que un proceso que
                                      o
    tiene asignados 4 marcos de p´ gina genera la siguiente secuencia de referen-
                                 a
    cias a p´ ginas:
            a
                     4,2,4,1,6,3,2,5,6,4,1,3,5,3
     Indica qu´ accesos producir´an un fallo de p´ gina cuando se utiliza cada una
               e                 ı               a
                                                       ´
     de las pol´ticas de reemplazo local FIFO, LRU y optima.
               ı

80. Se ha de dise˜ ar un sistema de paginaci´ n bajo demanda en el que se utiliza
                  n                          o
    una pol´tica de reemplazo local con tres marcos de p´ gina asignados para
            ı                                               a




                               @ibaumo
    cada proceso. Para la siguiente secuencia de referencias a p´ ginas: 1, 2, 3,
                                                                a
    2, 1, 5, 6, 3, 2, 1 ¿qu´ pol´tica de reemplazo producir´a un resultado m´ s
                            e    ı                            ı                a
                  ´
    cercano a la optima, FIFO o LRU? Demu´ stralo indicando los accesos que
                                               e
    producir´an fallo de p´ gina para cada uno de los m´ todos.
              ı            a                           e




                                                                    37

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        40   100 Ejercicios resueltos de Sistemas Operativos - UJI
Cap´tulo 5
   ı

Ejercicios Generales

81. Escribe un programa para limpiar el directorio /tmp. Recorriendo todos los
    subdirectorios que se encuentren a partir de /tmp, el programa debe eliminar
    todos los ficheros (de cualquier tipo) que pertenezcan al usuario que ejecuta
    el programa para los que haga m´ s de 2 semanas que no se acceden. En el
                                       a
    caso concreto de los directorios, se deben eliminar los que ya estaban vac´os
                                                                              ı
    o queden vac´os al eliminar los ficheros que conten´an, independientemente
                 ı                                       ı
                                         ´
    del tiempo transcurrido desde su ultimo acceso. Adem´ s, debe identificar
                                                              a




                             @ibaumo
    los ficheros para los que haga m´ s de 1 semana pero menos de 2 que no se
                                      a
    acceden e informar al usuario de que ser´ n borrados pr´ ximamente.
                                             a              o
        El programa recibir´ como par´ metro una direcci´ n de correo electr´ nico a
                            a          a                 o                  o
        la que enviar´ dos mensajes. El primer mensaje indicar´ en el asunto Fiche-
                     a                                         a
        ros borrados de /tmp y contendr´ el nombre de cada fichero o directorio que
                                        a
        se haya eliminado. El segundo mensaje indicar´ en el asunto Ficheros que se
                                                      a
        borrar´ n en breve y contendr´ los nombres de los ficheros para los que haga
               a                     a
        m´ s de 1 semana pero menos de 2 que no se acceden. Los nombres de los
          a
        ficheros en los dos mensajes deber´ n estar ordenados alfab´ ticamente. Para
                                           a                       e
        el env´o de los mensajes de correo electr´ nico se emplear´ la orden: mail
              ı                                   o                a
         direcci´ n correo  -s asunto Para realizar las acciones requeridas, el
                  o
        programa deber´ crear procesos y tuber´as de acuerdo al esquema que se
                        a                       ı
        muestra en la figura 5.1.




                                   Figura 5.1: Esquema de funcionamiento.

                         ´
        F´jate en que un unico proceso recorre el directorio /tmp y escribe en una
          ı
        tuber´a los nombres de los ficheros y directorios que borra y en otra tuber´a
             ı                                                                    ı

                                                                  39
J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        41   100 Ejercicios resueltos de Sistemas Operativos - UJI
distinta los nombres de los ficheros que se borrar´ n pr´ ximamente. Otros dos
                                                      a     o
     procesos independientes son los encargados de la ordenaci´ n de los nombres
                                                                 o
                                ı         ´
     almacenados en las tuber´as y, por ultimo, dos procesos m´ s enviar´ n los
                                                                   a        a
     mensajes de correo electr´ nico. En total, debes manejar 5 procesos y cuatro
                               o
     tuber´as como se muestra en la figura 5.1.
           ı

82. Escribe un programa que cree dos procesos de manera que, a partir de dos
    directorios dados como par´ metros de entrada, uno de los procesos realice
                                 a
    una b´ squeda de los ficheros con terminaci´ n .c y .h que se encuentren a
          u                                       o
                                                            ´
    partir del primer directorio dado (deber´ s recorrer el arbol de directorios) y
                                             a
    env´e su ruta a trav´ s de una tuber´a a un segundo proceso que crear´ una
        ı                e              ı                                    a
    copia en el segundo directorio. La copia s´ lo se debe realizar si se dan las
                                                o
    dos siguientes condiciones:

               El fichero encontrado no existe en el segundo directorio.
                                                                            ´
               El fichero existe en el segundo directorio, pero el tiempo de ultima
               modificaci´ n de la copia es anterior al del original.
                        o

     Para realizar la copia de cada fichero otro proceso deber´ ejecutar el siguiente
                                                             a
     comando: cp ruta fichero segundo directorio

83. Escribe un programa en C que convierta ficheros en formato postscript a for-




                               @ibaumo
    mato pdf. El programa recibir´ como par´ metros una serie de nombres de
                                   a           a
    directorios y, para cada uno de ellos, deber´ crear un proceso que lo recorra
                                                a
    recursivamente. Todos estos procesos deben ejecutarse en paralelo. Cada vez
    que se encuentre un fichero cuyo nombre termine en .ps, se considerar´ que
                                                                            a
    se trata de un fichero en formato postscript y se obtendr´ un fichero equiva-
                                                             a
    lente en formato pdf mediante el comando:

                         ps2pdf  ruta f ichero.ps   ruta f ichero.pdf 

     Una vez generado el fichero pdf, se debe borrar el fichero postscript corres-
     pondiente. Puedes suponer que el n´ mero de enlaces duros de cada fichero
                                        u
     postscript ser´ siempre uno.
                   a
     Antes de la finalizaci´ n de cada proceso, se deber´ informar de los siguientes
                          o                            a
     aspectos:

           - N´ mero de ficheros transformados.
              u
           - Ahorro de espacio en disco medido en n´ mero de bloques.
                                                   u
           - Tiempo total en segundos que se ha empleado en procesar el directorio
             correspondiente.

84. Escribe un programa en C que realice una simulaci´ n de la asignaci´ n de
                                                          o               o
    grupos de pr´ cticas a los estudiantes matriculados en una determinada asig-
                 a
    natura. El programa recibir´ como par´ metros en la l´nea de comandos:
                                 a          a             ı

                                                                    40

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        42   100 Ejercicios resueltos de Sistemas Operativos - UJI
- el n´ mero de estudiantes matriculados en la asignatura,
         u
   - la cantidad de grupos de pr´ cticas que existen, y
                                a
   - el n´ mero de plazas en cada grupo de pr´ cticas.
         u                                   a

Puedes suponer que el n´ mero de estudiantes siempre ser´ menor o igual que
                         u                                  a
el n´ mero total de plazas de pr´ cticas disponibles, es decir, que
    u                           a

   numero estudiantes ≤ cantidad de grupos × plazas por grupo

El programa deber´ crear una serie de hilos que se ejecuten en paralelo, de
                    a
modo que haya un hilo que simule el comportamiento de cada estudiante.
Adem´ s, habr´ otro hilo gestor que ser´ el encargado de realizar la asigna-
       a       a                          a
ci´ n de estudiantes a grupos de pr´ cticas, teniendo en cuenta las preferencias
  o                                a
de cada estudiante. Cada hilo correspondiente a un estudiante debe realizar
las siguientes acciones:

  a) Decidir el orden de preferencia de los grupos de pr´ cticas.
                                                        a
  b) Enviar de una en una al gestor una serie de peticiones de inclusi´ n en
                                                                         o
     los grupos de pr´ cticas seg´ n el orden decidido en el punto anterior. La
                      a          u
     petici´ n que se env´a al gestor debe contener dos datos:
           o             ı




                               @ibaumo
            - n´ mero de estudiante que hace la petici´ n, y
               u                                      o
            - n´ mero de grupo que se solicita.
               u

Para cada petici´ n recibida, el hilo gestor debe mostrar en la pantalla un
                o
mensaje que indique:

   - Si la acepta porque hay plazas libres en el grupo y el estudiante a´ n no
                                                                        u
     tiene ning´ n grupo asignado.
               u
   - Si la rechaza porque el grupo solicitado no tiene plazas disponibles.
   - Si la rechaza porque a ese alumno ya se le hab´a asignado otro grupo
                                                       ı
     de pr´ cticas (es decir, se le hab´a aceptado una petici´ n anterior).
           a                           ı                     o

F´jate en que los estudiantes env´an peticiones para todos los grupos de
  ı                                 ı
pr´ cticas ordenadas seg´ n sus preferencias. El gestor procesar´ todas las so-
    a                   u                                       a
licitudes y rechazar´ las correspondientes a estudiantes que ya tienen asig-
                    a
nado un grupo de pr´ cticas o a grupos que est´ n llenos.
                     a                         a
La comunicaci´ n entre los hilos correspondientes a los estudiantes y el hilo
                o
gestor debe realizarse a trav´ s de un buffer intermedio en el que se podr´ n
                             e                                            a
almacenar como m´ ximo 20 peticiones. Debes garantizar que todos los ac-
                    a
cesos al buffer sean correctos.
Para simplificar la soluci´ n del problema, considera que ya est´ n definidas
                          o                                    a
las siguientes variables globales, estructuras y funciones:

                                                            41

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   43   100 Ejercicios resueltos de Sistemas Operativos - UJI
/* Variables globales.
        IMPORTANTE. Debes inicializarlas en el programa principal seg´n los
                                                                     u
                    par´metros de la l´nea de comandos.
                       a              ı                                                                 */
     int num_estudiantes, cantidad_grupos, plazas_por_grupo;

     /* Tipos de datos */
     typedef struct {
       int num_estudiante;
       int num_grupo;
     } TipoPeticion;

     /* Funciones */

     int *decide_preferencias(int num_estudiante);
       /* Devuelve un vector de enteros en el que los grupos de pr´cticas
                                                                   a
          est´n ordenados seg´n las preferencias del estudiante */
             a               u

     int grupo_asignado(int num_estudiante);
       /* Devuelve el n´mero de grupo de pr´cticas asignado a un estudiante.
                       u                   a
          Si todav´a no se le ha asignado ning´n grupo devuelve -1 */
                  ı                           u

     int hay_plazas_libres(int num_grupo);
       /* Devuelve 1 si hay plazas libres en el grupo dado o 0 en caso contrario */

     void asignar_grupo(int num_estudiante, int num_grupo);
       /* Asigna el estudiante al grupo indicado */


     En concreto, se te pide que proporciones:




                               @ibaumo
           - La funci´ n que simula el comportamiento de un estudiante.
                     o
           - La funci´ n que simula el gestor de peticiones.
                     o
           - El programa principal, que debe incluir todas las inicializaciones que
             sean necesarias, la creaci´ n de todos los hilos y la espera hasta que
                                       o
             todos ellos terminen.
           - Todos los tipos, variables, etc. que puedas necesitar y que no aparezcan
             ya definidos en el enunciado.

85. Escribe un programa en C que imprima los ficheros regulares que encuen-
    tre en una serie de directorios dados como par´ metros. Para cada directorio
                                                   a
    se deber´ crear un proceso que lo recorra recursivamente de modo que to-
              a
    dos ellos se ejecuten en paralelo. Los ficheros cuyo tama˜ o sea menor de
                                                               n
    2 Mbytes se enviar´ n a la cola de impresi´ n ps1 y el resto se enviar´ a la
                        a                      o                           a
    cola de impresi´ n ps2. Para enviar un fichero a una cola de impresi´ n se de-
                    o                                                  o
    ber´ ejecutar el siguiente comando: lpr -P cola fichero. Antes de la
        a
    finalizaci´ n del programa se deber´ indicar el tiempo total empleado en la
               o                        a
    ejecuci´ n del mismo.
            o
     NOTA: Se incluye una versi´ n de la funci´ n de recorrido recursivo de un
                               o              o
     directorio:




                                                                    42


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        44   100 Ejercicios resueltos de Sistemas Operativos - UJI
void recorre(char ∗nombredir) {
       DIR ∗d;
       struct dirent ∗entrada;
       struct stat datos;
       char ∗ruta;

         printf(empiezo a recorrer %sn, nombredir);
         d= opendir(nombredir);
         if (d== NULL) {
           printf(Error al abrir el directorion);
           return;
         }

         entrada= readdir(d);
         while (entrada!= NULL) {
           if (strcmp(entrada-d name, .) 
               strcmp(entrada-d name, ..)) {
             ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2);
             sprintf(ruta, %s/ %s, nombredir, entrada-d name);
             lstat (ruta, datos);
             if (S ISDIR (datos.st mode))
               recorre (ruta);
             printf (Procesando %sn, ruta);
             free (ruta);
           }
           entrada= readdir(d);
         }
         closedir(d);
     }




                               @ibaumo
86. Se desea realizar una simulaci´ n de una granja de gallos en la que hay dos
                                     o
    tipos de gallos: dom´ sticos y salvajes. En la granja, la vida de un gallo cual-
                          e
    quiera consiste b´ sicamente en comer, beber y dormir en este orden. Para
                       a
    realizar la acci´ n de beber se accede a una fuente de agua com´ n para todos
                    o                                                 u
    los gallos y se evita que un gallo salvaje se junte con gallos dom´ sticos o con
                                                                       e
    otros gallos salvajes mientras dure la acci´ n. Por contra, un gallo dom´ stico
                                                 o                            e
    si que puede realizar la acci´ n de beber junto a otros gallos dom´ sticos. Res-
                                  o                                    e
    pecto a las acciones de comer y dormir no se establece ninguna condici´ n.   o
    La granja cuenta con un total de 30 gallos, 25 de ellos dom´ sticos y el resto
                                                                   e
    salvajes. Utiliza el programa que se acompa˜ a para resolver las siguientes
                                                     n
    cuestiones:

         a) En primer lugar, se desea mejorar la funci´ n dormir de manera que aho-
                                                      o
            ra tendr´ dos par´ metros de entrada: void dormir (int id, int tiempo);.
                    a         a
            La variable id es un identificador del gallo y tiempo ser´ el tiempo que
                                                                     a
            va a dormir (un valor entero aleatorio entre 7 y 10). Modifica el progra-
            ma principal de manera que, para cada gallo de la simulaci´ n, se env´e
                                                                        o         ı
            ambos par´ metros a las funciones correspondientes galloDomestico y
                       a
                                      ´
            galloSalvaje, y modifica estas tambi´ n de forma conveniente.
                                                 e
         b) Realiza las modificaciones oportunas de manera que se simule la vida
            de los gallos dom´ sticos y salvajes tal y como se explica en el enuncia-
                             e
            do.

                                                                    43


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        45   100 Ejercicios resueltos de Sistemas Operativos - UJI
c) Limita el n´ mero de gallos dom´ sticos realizando la acci´ n de beber al
                       u                   e                          o
            mismo tiempo a 6.
     #include stdio.h
     #include stdlib.h
     #include semaphore.h
     #include pthread.h
     #include unistd.h
     #include time.h
     #define N 30;

     /∗ simula la vida de un gallo salvaje ∗/
     void ∗galloSalvaje (void ∗nada){

         while (1) {
           comer(); /∗ funci´n que simula la acci´n de comer ∗/
                             o                    o
           beber(); /∗ funci´n que simula la acci´n de beber ∗/
                             o                    o
           dormir(); /∗ funci´n que simula la acci´n de dormir ∗/
                             o                    o
         }
         pthread exit(NULL);
     }

     /∗ simula la vida de un gallo dom´stico ∗/
                                      e
     void ∗galloDomestico (void ∗nada){

         while (1) {
           comer();   /∗ funci´n que simula la acci´n de comer ∗/
                              o                    o
           beber();   /∗ funci´n que simula la acci´n de beber ∗/
                              o                    o
           dormir(); /∗ funci´n que simula la acci´n de dormir ∗/
                              o                    o




                               @ibaumo
         }
         pthread exit(NULL);
     }

     int main (int argc, char ∗argv[]) {

         pthread t th[N];
         int i;

         for (i= 0; i 25; i++) /∗                            crea los gallos dom´sticos ∗/
                                                                                 e
           pthread create (th[i],                            NULL, galloDomestico, NULL);
         for (i= 25; i N; i++) /∗                            crea los gallos salvajes ∗/
           pthread create (th[i],                            NULL, galloSalvaje, NULL);

         for (i= 0; i N; i++)
           pthread join(th[i], NULL);

         exit(0);
     }



87. Escribe un programa en C que ejecute en paralelo cuatro hilos. De ellos, tres
    ser´ n productores de datos y uno consumidor. Los hilos se comunicar´ n a
       a                                                                    a
    trav´ s de un buffer intermedio en el que se podr´ n almacenar como m´ ximo
        e                                            a                    a
    5 datos.
     Cada hilo productor se encarga de generar como m´ ximo 1000 n´ meros alea-
                                                         a             u
     torios. Para cada n´ mero generado, comprueba si es un n´ mero primo y, de
                         u                                        u
     ser as´, lo almacena en el buffer. El hilo consumidor extrae n´ meros del buf-
           ı                                                        u
     fer y escribe en pantalla aquellos n´ meros para los que la suma de sus d´gitos
                                         u                                    ı

                                                                    44

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        46                   100 Ejercicios resueltos de Sistemas Operativos - UJI
sea impar.
     El programa terminar´ cuando el hilo consumidor haya escrito cincuenta
                            a
     n´ meros en pantalla o cuando cada productor haya generado sus 1000 n´ me-
      u                                                                    u
     ros aleatorios. Antes de terminar, el programa informar´ de la cantidad de
                                                              a
     n´ meros primos procesados y la cantidad de n´ meros aleatorios generados.
      u                                            u
     Puedes considerar que las siguientes funciones ya est´ n definidas:
                                                          a

               int numero_aleatorio(void);
               int es_primo(int numero);
               int suma_digitos(int numero);


88. Escribe un programa para limpiar el directorio /tmp. Recorriendo todos los
    subdirectorios que se encuentren a partir de /tmp, el programa debe eliminar
    todos los ficheros regulares que pertenezcan al usuario que ejecuta el pro-
    grama y cuyo tama˜ o sea superior a 2 Mbytes. Adem´ s, se deben eliminar
                        n                                   a
    los directorios que ya estaban vac´os o queden vac´os al eliminar los ficheros
                                      ı                ı
    que conten´an. Tambi´ n se deben identificar los ficheros regulares que ocu-
                ı          e
    pen m´ s de 1 Mbyte pero menos de 2 Mbytes para informar al usuario de
           a
    que esos ficheros est´ n ocupando una gran cantidad de espacio en disco.
                         a
     El programa recibir´ como par´ metro una direcci´ n de correo electr´ nico a
                        a           a                 o                  o
     la que enviar´ dos mensajes. El primer mensaje indicar´ en el asunto Fiche-
                  a                                        a
     ros borrados de /tmp y contendr´ el nombre de cada fichero o directorio que
                                     a



                               @ibaumo
     se haya eliminado. El segundo mensaje indicar´ en el asunto Ficheros que
                                                    a
     ocupan mucho espacio en /tmp y contendr´ el nombre y tama˜ o en bytes de
                                               a                  n
     cada fichero cuyo tama˜ o est´ entre 1 y 2 Mbytes.
                            n     e
     Para el env´o de los mensajes de correo electr´ nico se emplear´ la orden:
                ı                                  o                a

                                       mail direcci´ n correo -s asunto
                                                    o

     Para realizar las acciones requeridas, el programa deber´ crear procesos y
                                                             a
     tuber´as de acuerdo al esquema que se muestra en la figura 5.2.
          ı




                                Figura 5.2: Esquema de funcionamiento.

                      ´
     F´jate en que un unico proceso recorre el directorio /tmp y escribe en una
       ı
     tuber´a los nombres de los ficheros y directorios que borra y en otra tuber´a
           ı                                                                   ı
     distinta los nombres de los ficheros que ocupan m´ s de 1 Mbyte. Otros dos
                                                       a

                                                                    45

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        47   100 Ejercicios resueltos de Sistemas Operativos - UJI
procesos independientes son los encargados de enviar los mensajes de correo
     electr´ nico. En total, debes manejar 3 procesos y 2 tuber´as como se muestra
           o                                                   ı
     en la figura.

89. Un programador quiere simular el movimiento de camiones y barcos en una
    estaci´ n petroqu´mica. Los barcos llegan a la estaci´ n para descargar de sus
          o          ı                                   o
    bodegas el producto crudo que posteriormente se refina y se carga en los
    tanques de los camiones que van llegando a la estaci´ n. Las condiciones de
                                                           o
    funcionamiento de la estaci´ n que ha de tener en cuenta el programador son:
                               o

         a) La estaci´ n tiene capacidad para atender a tantos camiones como lle-
                     o
            guen.
         b) La estaci´ n tiene capacidad para atender a los barcos de uno en uno.
                     o
         c) Mientras se atiende a un barco no se puede atender a nuevos camiones
            pero s´ a los camiones que hubiesen ya en la estaci´ n.
                  ı                                            o

     En base a estas condiciones, el programador escribe el siguiente c´ digo:
                                                                       o
     #include           stdio.h
     #include           stdlib.h
     #include           semaphore.h
     #include           pthread.h
     #include           unistd.h




                               @ibaumo
     #define N vehiculos 200
     sem t estacion;

     void ∗camion (void ∗ nada) {

         long int n= (long int) pthread self();

         printf (Llega camion: %ldn, n);
         sem wait(estacion);
         printf (Se atiende camion: %ldn, n);
         sleep(random() %3+2); /∗ tiempo invertido en atender al camion ∗/
         printf (Sale camion: %ldn, n);
         pthread exit(NULL);
     }

     void ∗barco (void ∗ nada) {

         long int n= (long int) pthread self();

         printf (Llega barco: %ldn, n);
         sem wait(estacion);
         printf(Se atiende barco: %ldn, n);
         sleep(random() %5+5); /∗ tiempo invertido en atender al barco ∗/
         printf (Sale barco: %ldn, n);
         sem post(estacion);
         pthread exit(NULL);
     }

     int main(int argc, char ∗argv[]) {

         int i;
         pthread t th;



                                                                    46

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        48   100 Ejercicios resueltos de Sistemas Operativos - UJI
for (i= 0; i N vehiculos; i++) {
           sleep(random() %3);
           if (random() %100  95)
             pthread create(th, NULL, camion, NULL);
           else
             pthread create(th, NULL, barco, NULL);
         }
         for (i= 0; i N vehiculos; i++)
           pthread join(th, NULL);

         return 0;
     }

     Se pide:

         a) Puesto que el c´ digo anterior contiene errores y no satisface las tres
                           o
            condiciones descritas en el enunciado, corrige los errores e indica las
            modificaciones necesarias para que se satisfagan.
         b) Haz las modificaciones oportunas (al programa resultado del apartado
            anterior) para que, sin dejar de cumplirse las condiciones de funciona-
            miento a) y b), se cumpla tambi´ n la siguiente nueva condici´ n:
                                             e                            o
                  1) Mientras se atiende a un barco no se puede atender a nuevos ca-
                     miones y el barco s´ lo puede ser atendido cuando no hayan ca-
                                         o
                     miones utilizando la estaci´ n.
                                                o




                               @ibaumo
                                                             ´
90. Escribe un programa que ejecute la siguiente l´nea de ordenes igual que lo
                                                    ı
    har´a un int´ rprete de comandos:
       ı        e
                grep palabra file1 | sort -r | uniq  file salida
     y que adem´ s nos diga cu´ nto tiempo (en segundos) ha tardado en ejecu-
                 a             a
     tarse completamente. Tanto file1, file salida como palabra ser´ n par´ metros
                                                                 a      a
     dados por tu programa en la l´nea de comandos en ese orden.
                                  ı

91. Simula el movimiento de personas que entran y salen de una sucursal banca-
    ria teniendo en cuenta las siguientes condiciones. En dicha sucursal, durante
    el horario de atenci´ n al p´ blico, un furg´ n blindado puede llegar para la
                           o      u              o
    carga y descarga de dinero. Para que se realice esta operaci´ n, es necesario
                                                                  o
    que no haya clientes en el interior de la sucursal, por lo que los guardias de
    seguridad del furg´ n deben esperar a que la sucursal se encuentre vac´a an-
                         o                                                    ı
    tes de iniciar la operaci´ n. La sucursal puede atender a tantos clientes como
                             o
    lleguen, no hay l´mite de capacidad. Utiliza el programa que se acompa˜ a,
                       ı                                                        n
    que contiene alg´ n error, y da dos soluciones al problema, una por cada una
                      u
    de las siguientes condiciones respecto al momento de llegada del furg´ n a la
                                                                             o
    sucursal:

         a) Que no se impida la entrada de nuevos clientes a la sucursal mientras
            existan clientes en su interior.
         b) Que s´ se impida la entrada de nuevos clientes a la sucursal.
                 ı

                                                                    47


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        49   100 Ejercicios resueltos de Sistemas Operativos - UJI
(Recuerda que en ambos casos, la operaci´ n no puede empezar hasta que la
                                                o
     sucursal est´ sin clientes, como ya se deja claro en el enunciado)
                 e
     #include           stdlib.h
     #include           stdio.h
     #include           semaphore.h
     #include           pthread.h
     #include           unistd.h
     #include           time.h

     #define N hilos 200

     void ∗cliente (void ∗n){

         int id= ∗(int ∗)n;

         sleep          (random() %100);
         printf         (Llega el cliente %dn, id);
         sleep          (random() %3+2); /∗ tiempo de espera en la cola ∗/
         printf         (Se atiende al cliente: %dn, id);
         sleep          (random() %3+2); /∗ tiempo invertido en la operacion ∗/
         printf         (Sale el cliente %dn,id);

         pthread exit(NULL);
     }



     void ∗furgon (void ∗n){




                               @ibaumo
         int id= ∗(int ∗)n;

         sleep          (random() %100);
         printf         (LLega el furgon %dn, id);
         printf         (Se atiende a los guardias %dn, id);
         sleep          (random() %5 + 5); /∗ tiempo invertido en la operacion ∗/
         printf         (Se va el furgon %dn,id);

         pthread exit(NULL);
     }

     int main ( int argc, char ∗ argv[]) {

         pthread t hilo;
         int i, furgon creado= 0;

         for (i= 0; i N hilos; i++)
           if (furgon creado== 1)
             pthread create(hilo, NULL, cliente, (void ∗) i);
           else
             if (random() %100  95)
                pthread create(hilo, NULL, cliente, (void ∗) i);
             else {
               pthread create(hilo, NULL, furgon, (void ∗) i);
               furgon creado= 1;
             }
         return 0;
     }


92. Se desea realizar una implementaci´ n en C del problema cl´ sico del productor-
                                       o                      a
    consumidor. Las caracter´sticas propias de esta implementaci´ n son:
                             ı                                    o

                                                                    48

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        50   100 Ejercicios resueltos de Sistemas Operativos - UJI
Los hilos se comunican a trav´ s de un b´ ffer intermedio de capacidad
                                    e          u
       10.
       El hilo productor produce un n´ mero aleatorio de datos.
                                     u
       El hilo consumidor escribe el n´ mero consumido en la pantalla.
                                      u
       El programa termina cuando se hayan consumido los datos producidos.

En concreto, se pide:

  a) Escribe el programa principal que: crea, inicializa y destruye los sem´ fo-
                                                                           a
     ros; crea dos hilos, uno productor y otro consumidor; espera a que se
     cumpla la condici´ n de terminaci´ n del programa.
                       o              o
  b) Escribe el c´ digo del hilo productor y del consumidor.
                 o
  c) Escribe las modificaciones oportunas para que en lugar de un hilo pro-
     ductor hayan tres que se ejecuten en paralelo y garantizando que se
     consumen todos los datos.
  d) Escribe las modificaciones oportunas para que en lugar de un hilo con-
     sumidor hayan dos que se ejecuten en paralelo (es decir, tendremos tres
     productores y dos consumidores).

NOTA: Se incluye una versi´ n incompleta del c´ digo.
                          o                   o




                               @ibaumo
#include       stdio.h
#include       stdlib.h
#include       semaphore.h
#include       pthread.h
#include       unistd.h
#include       time.h

#define MAX 10

int buffer[MAX];

int pos productor= 0, pos consumidor= 0;
int menos uno= 0;

int genera dato(void);
int numero aleatorio(void);

void ∗productor (void ∗nada) {
  int i, dato, n= numero aleatorio();
  for(i=0; i n; i++){
    dato= generar dato();
    sleep(random() %2);
    buffer[pos productor]= dato;
    pos productor= (pos productor+1) %MAX;
  }
  buffer[pos productor]= -1;
  pos productor= (pos productor+1) %MAX;
  pthread exit(NULL);
}




                                                            49

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   51   100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗consumidor (void ∗nada) {
       int i,dato;
       while(menos uno!= 1){
         dato= buffer[pos consumidor];
         pos consumidor= (pos consumidor+1) %MAX;
         if (dato== -1)
           menos uno++;
         printf ( %d , dato);
         sleep(random( %2));
       }
       pthread exit(NULL);
     }


93. Escribe un programa en C que, a partir de una serie de directorios que se pro-
    porcionan como par´ metros, los recorra recursivamente y calcule cu´ ntos en-
                        a                                                a
    laces simb´ licos hay dentro de ellos. El programa debe crear un hilo por cada
                o
    directorio dado, de modo que el recorrido de cada uno de ellos se ejecute en
    paralelo con el resto. Por simplicidad, se considerar´ que nunca habr´ m´ s
                                                          a                 a a
    de 10 directorios como par´ metros. Tanto para los directorios dados como
                                a
    par´ metros como para los que aparezcan en el recorrido recursivo de los
        a
    mismos, s´ lo se deben tener en cuenta aquellos directorios que pertenezcan
               o
    al usuario que ejecuta el programa. El resto de directorios simplementen se
    ignorar´ n.
            a
     Nota. No se pide el n´ mero de enlaces que hay en cada uno de los directorios
                          u




                               @ibaumo
     dados, sino la suma de todos ellos. Es decir, el resultado del programa debe
            ´
     ser un unico n´ mero.
                   u

94. Se desea escribir un programa que implemente una primera aproximaci´ n a  o
    la generaci´ n de un cierto tipo de claves criptogr´ ficas. Para ello, se deben
               o                                       a
    encontrar pares de n´ meros p y q tales que:
                        u

               p y q sean primos;
               (p − 1)/2 y (q − 1)/2 tambi´ n sean primos.
                                          e

     Si se cumplen estas dos condiciones, entonces el producto p ∗ q nos propor-
     ciona una clave criptogr´ fica. Para resolver el problema planteado se utiliza
                              a
     una estrategia productor-consumidor mediante tres procesos que se ejecutan
     en paralelo de la siguiente forma:

               Dos procesos productores se encargan de analizar secuencialmente to-
               dos los n´ meros de un rango dado para averiguar cu´ les de ellos son
                        u                                          a
               primos.
               Un proceso consumidor que, repetidamente, toma un par cualquiera de
               n´ meros primos de los encontrados por los productores y comprueba
                u
               si dicho par de n´ meros cumplen los requisitos necesarios para generar
                                u
               una clave criptogr´ fica. En caso afirmativo, muestra por pantalla los
                                   a
               dos n´ meros utilizados y el valor de la clave criptogr´ fica generada. En
                     u                                                a

                                                                    50


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        52   100 Ejercicios resueltos de Sistemas Operativos - UJI
cualquier caso, estos dos n´ meros utilizados ser´ n descartados y no se
                                          u                     a
               volver´ n a considerar.
                     a

     Al acabar la ejecuci´ n, el programa debe indicar la cantidad total de n´ meros
                         o                                                   u
     primos que han encontrado los productores, as´ como el n´ mero de claves
                                                      ı            u
     criptogr´ ficas generadas.
             a
     Escribe un programa en C que proporcione una soluci´ n v´ lida al problema
                                                        o a
     utilizando tuber´as.
                     ı

95. Resuelve el ejercicio 94 utilizando 3 hilos (2 productores y 1 consumidor)
    que ahora se comunican a trav´ s de un buffer intermedio de capacidad 20
                                    e
    elementos en lugar de utilizar tuber´as. La sincronizaci´ n en la ejecuci´ n de
                                        ı                   o                o
    los hilos se debe realizar mediante sem´ foros.
                                            a

96. Escribe un programa que, a partir de un directorio dado como par´ metroa
    comprima y a˜ ada al fichero /tmp/comprimido.zip todos los ficheros regu-
                   n
                                                                         ´
    lares que encuentre a partir de dicho directorio (deber´ recorrer el arbol de
                                                           a
    directorios a partir de dicho directorio) tales que:

               Pertenezcan al usuario que ejecuta el programa.
                                           ´
               Se hayan modificado desde la ultima hora (medida desde el inicio de la




                               @ibaumo
               ejecuci´ n del programa).
                      o

     Para comprimir un fichero fich y a˜ adirlo al fichero /tmp/comprimido.zip uti-
                                        n
     liza el programa zip de la siguiente forma: $ zip /tmp/comprimido.zip fich.
     Ten en cuenta que no se pueden hacer varias acciones zip sobre el mismo ar-
     chivo de manera simult´ nea. Adem´ s, por cada fichero regular que encuen-
                             a           a
     tres que cumpla las condiciones anteriores deber´ s enviar su ruta a trav´ s
                                                      a                       e
     de una tuber´a a otro proceso que crear´ un fichero llamado usuario.log que
                 ı                           a
     contendr´ un informe ordenado, utiliza el comando sort, de las rutas de los
              a
     ficheros regulares a˜ adidos al archivo zip.
                         n

97. En una reuni´ n de atletismo, hay tres tipos de atletas participantes. Por un
                 o
    lado los lanzadores de jabalina, por otro los lanzadores de martillo y por
    ´
    ultimo los corredores. A primera hora del d´a se les da acceso libre a las ins-
                                                 ı
    talaciones para entrenar. Por seguridad, se han establecido unas restricciones
    de uso de las instalaciones:

         a) Un atleta lanzador de martillo o de jabalina debe esperar para entrar
            en las instalaciones a que no haya ning´ n atleta, sea del tipo que sea,
                                                   u
            utiliz´ ndolas.
                  a
         b) Si hay un atleta lanzador de jabalina o de martillo utilizando las insta-
            laciones, un nuevo atleta que llegue, sea del tipo que sea, debe esperar
            para entrar en las instalaciones a que el que ya hay la abandone.

                                                                    51

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        53   100 Ejercicios resueltos de Sistemas Operativos - UJI
c) Si en las instalaciones hay alg´ n atleta corredor y llega un nuevo atle-
                                      u
       ta corredor, este entrar´ en las instalaciones incluso aunque hubiesen
                               a
       atletas lanzadores esperando para entrar.

Se pide:

         Completa el c´ digo que se te da a continuaci´ n de forma que se simule
                      o                               o
                                                            ´
         el comportamiento descrito en el enunciado. Las ordenes printf deben
         permanecer en tu soluci´ n. Sit´ alas donde debas.
                                o       u
         Modifica el c´ digo soluci´ n del apartado anterior para que se respete
                       o            o
         el orden de llegada de los atletas a las instalaciones. De esta forma, si
         llega un nuevo atleta corredor habiendo atletas lanzadores esperando, el
         atleta corredor deber´ esperar a que entren y salgan de las instalaciones
                               a
                                                ´
         los lanzadores que llegaron antes que el, incluso aunque en el momento
         de la llegada hubiesen atletas corredores en las instalaciones.
#include         stdio.h
#include         stdlib.h
#include         semaphore.h
#include         pthread.h
#include         unistd.h
#include         sys/syscall.h

#define N atletas 30




                                 @ibaumo
void ∗corredor (void ∗ nada) {

    int n=       (int) syscall(SYS gettid);
    printf       (Llega corredor: %dn, n);
    printf       (Entra en las instalaciones el corredor %dn, n);
    sleep        (random() %3); /∗ tiempo invertido en usarlas ∗/
    printf       (Sale de las instalaciones el corredor: %dn, n);

    pthread exit(NULL);
}

void ∗jabalino (void ∗ nada) {

    int n=       (int) syscall(SYS gettid);
    printf       (Llega lanzador de jabalina: %dn, n);
    printf       (Entra en las instalaciones el jabalino %dn, n);
    sleep        (random() %3+2); /∗ tiempo invertido en usarlas ∗/
    printf       (Sale de las instalaciones el jabalino: %dn, n);

    pthread exit(NULL);
}

void ∗martillo (void ∗ nada) {

    int n=       (int) syscall(SYS gettid);
    printf       (Llega lanzador de martillo: %dn, n);
    printf       (Entra en las instalaciones el martillo %dn, n);
    sleep        (random() %3+2); /∗ tiempo invertido en usarlas ∗/
    printf       (Sale de las instalaciones el martillo: %dn, n);

    pthread exit(NULL);
}


                                                              52

    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   54   100 Ejercicios resueltos de Sistemas Operativos - UJI
int main (int argc, char ∗argv[]) {

         int num;
         pthread t th[N atletas];

         for (num= 0; num N atletas; num++) {
           sleep(random() %3);
           if (random() %100  66)
             pthread create(th[num], NULL, corredor, NULL);
           else
             if (random() %100  82)
           pthread create(th[num], NULL, jabalino, NULL);
             else
           pthread create(th[num], NULL, martillo, NULL);
         }

         for (num= 0; num N atletas; num++)
           pthread join(th[num], NULL);

         return 0;
     }


98. En un concurso televisivo de la canci´ n denominado Egovision participan
                                          o
    grupos musicales en representaci´ n de diferentes pa´ses. Despu´ s de las ac-
                                      o                 ı          e
    tuaciones, comienza la fase de la votaci´ n. En esta fase, cada persona del
                                            o
    p´ blico vota enviando un SMS indicando el pa´s y la puntuaci´ n entre 0 y
     u                                              ı              o
    10. Durante la fase de votaci´ n, cada pa´s participante puede consultar el
                                   o          ı




                               @ibaumo
    estado de las votaciones cuando quiera y cuantas veces desee. Escribe un
    programa en C que realice una simulaci´ n de este proceso y que adem´ s
                                             o                                 a
    satisfaga las siguientes condiciones:

               Utiliza un vector de enteros, de dimensi´ n el n´ mero de pa´ses, para
                                                       o        u          ı
               almacenar los puntos que cada pa´s recibe y ll´ malo puntuaciones.
                                                ı            a
               La simulaci´ n genera un total de 100 hilos.
                          o
               Cada hilo generado ser´ de tipo voto con una probabilidad del 90 % o
                                      a
               de tipo consulta con una probabilidad del 10 %.
               Cada hilo de tipo voto recibe dos datos generados de forma aleatoria,
               el pa´s votado (representado por un identificador de tipo entero) y una
                    ı
               puntuaci´ n, y acumula la nueva puntuaci´ n del pa´s indicado a la que
                        o                               o        ı
               ya hay en el vector puntuaciones.
               Cada hilo de tipo consulta recibe un dato generado de forma aleatoria:
               el pa´s que realiza la consulta. Se debe permitir que varias consultas
                    ı
               se puedan realizar de forma simult´ nea garantizando la coherencia de
                                                   a
               los datos mostrados, es decir, que si varios pa´ses realizan consultas al
                                                              ı
               mismo tiempo, entonces todos deben mostrar el mismo resultado.
               Para comprobar visualmente la simulaci´ n sit´ a en el c´ digo para cada
                                                       o     u         o
               tipo de hilo la impresi´ n de los mensajes, que se facilitan a continua-
                                      o
               ci´ n, de forma correcta.
                 o

                                                                    53



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        55   100 Ejercicios resueltos de Sistemas Operativos - UJI
#define NHILOS 100
     #define PAISES 10

     char paises[PAISES][10]={Espa˜ a, Portugal, Francia, Ucrania,
                                         n
     Letonia, Servia, Israel, Alemania, Italia, Holanda};

     int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0};

     funcion voto {

         imprime(Voto al pais %s %d puntosn,paises[pais],puntos);

         imprime(Ya he votado al pais %s %d puntosn,paises[pais],puntos);

     }

     funcion consulta {

         imprime (El pais %s realiza la consultan,paises[pais]);

         Para (int i=0; i PAISES;i++)
           imprime(( %s, %d)n,paises[i],puntuaciones[i]);

         imprime(El pais %s termina la consultan,paises[pais]);
     }


99. En un concurso televisivo de la canci´ n denominado Egovision participan
                                           o
    grupos musicales en representaci´ n de diferentes pa´ses. Despu´ s de las ac-
                                      o                 ı          e
    tuaciones, comienza la fase de la votaci´ n. En esta fase, cada persona del
                                             o



                               @ibaumo
    p´ blico vota enviando un SMS indicando el pa´s y la puntuaci´ n entre 0 y
     u                                              ı              o
    10. Escribe un programa en C que realice una simulaci´ n de este proceso y
                                                           o
    que adem´ s satisfaga las siguientes condiciones:
              a

               Utiliza un vector de enteros, de dimensi´ n el n´ mero de pa´ses, para
                                                       o        u           ı
               almacenar los puntos que cada pa´s recibe y ll´ malo puntuaciones.
                                                ı            a
               La simulaci´ n genera N procesos nuevos que en paralelo emiten un
                          o
               voto cada uno de ellos.
               Una tuber´a comunica los N procesos nuevos con el proceso principal.
                        ı
               Cada proceso que emite un voto genera dos datos de forma aleatoria:
               el pa´s al que vota (un identificador de tipo entero) y la puntuaci´ n co-
                     ı                                                           o
               rrespondiente. Ambos son enviados por la tuber´a al proceso principal.
                                                                 ı
               El proceso principal actualiza el resultado de la votaci´ n a medida que
                                                                       o
               le llegan los votos por la tuber´a. Una vez recogidos todos los votos,
                                               ı
               el resultado final se muestra ordenado (ver ejemplo a continuaci´ n). o
               Para conseguir la ordenaci´ n se env´a una l´nea de texto por pa´s, con
                                           o         ı      ı                    ı
               el formato del ejemplo, mediante una nueva tuber´a a un proceso que
                                                                   ı
               hace la ordenaci´ n de los datos recibidos mediante la orden sort -r.
                                o
                                      156 puntos, Espa˜a
                                                      n
                                      150 puntos, Alemania
                                      135 puntos, Holanda
                                      .
                                      .


                                                                    54


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        56    100 Ejercicios resueltos de Sistemas Operativos - UJI
No deben aparecer ni procesos hu´ rfanos ni procesos zombies.
                                                  e
        #define N 100
        #define PAISES 10

        char paises[PAISES][10]={Espa˜ a, Portugal, Francia, Ucrania,
                                            n
        Letonia, Servia, Israel, Alemania, Italia, Holanda};

        int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0};



100. Se desea conocer el n´ mero de nodo-i de cada uno de los ficheros que en un
                          u
     sistema dado tengan un tama˜ o superior a 1024 bloques. Tambi´ n se quiere
                                   n                                  e
     saber cu´ ntos ficheros satisfacen esta condici´ n. Escribe un programa en C
             a                                     o
     que, para conseguir ambos objetivos, act´ e de la siguiente manera:
                                              u

                  La b´ squeda de ficheros comienza siempre a partir de un directorio
                      u
                  dado como par´ metro de entrada.
                                a
                  Se podr´ n especificar varios directorios como par´ metros de entrada.
                         a                                         a
                  El proceso inicial deber´ crear tantos procesos de b´ squeda como di-
                                           a                          u
                  rectorios especificados como par´ metros de entrada y deber´ n ejecu-
                                                      a                        a
                                                               ´
                  tarse en paralelo tanto entre ellos como con el mismo. De esta manera,
                  cada proceso creado realizar´ la b´ squeda recursiva de ficheros en el
                                                 a      u
                  ´
                  arbol de directorios de uno de los directorios dados como par´ metros
                                                                                 a




                               @ibaumo
                  de entrada.

        Cuando un proceso de b´ squeda encuentre un fichero que satisfaga la condi-
                                  u
        ci´ n dada (tama˜ o superior a 1024 bloques), enviar´ su n´ mero de nodo-i a
          o              n                                      a     u
        trav´ s de una tuber´a a un proceso que realizar´ una ordenaci´ n de todos los
             e              ı                              a             o
        n´ meros recibidos utilizando el comando del sistema sort. Cuando un proce-
          u
                u                                         ´
        so de b´ squeda haya terminado de recorrer el arbol de directorios, enviar´ al
                                                                                    a
        proceso inicial, y a trav´ s de otra tuber´a, el n´ mero de ficheros encontrados
                                 e                ı       u
        que han cumplido la condici´ n dada. Una vez todos los procesos de b´ sque-
                                       o                                         u
        da creados hayan terminado, el proceso inicial informar´ del total de ficheros
                                                                   a
        encontrados.




                                                                    55

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        57   100 Ejercicios resueltos de Sistemas Operativos - UJI
Cap´tulo 6
   ı

Soluciones

   1. La jerarqu´a resultante se puede observar en la figura 6.1.
                ı




                   ı
del bucle en la que se crea.
                              @ibaumo
Figura 6.1: Jerarqu´a en profundidad donde para cada proceso se indica la iteraci´ n
                                                                                 o


         Aparecen mensajes repetidos porque la orden printf, la que hay dentro del
         bucle, la ejecuta cada proceso hijo una primera vez tras ser creado como
         resultado de la llamada al sistema fork que hay justo en la l´nea anterior del
                                                                      ı
         printf, y una segunda vez en la siguiente iteraci´ n del bucle (excepto en el
                                                          o
                                    ´
         caso de encontrarse en su ultima iteraci´ n).
                                                 o
         Se observa que los procesos terminan en el orden contrario al que se han
                                              ´                           ´
         creado, es decir, primero termina el ultimo proceso creado y el ultimo proce-
         so en terminar es el inicial. Esto ocurre gracias a la llamada al sistema wait
         que cambia el estado del proceso padre a bloqueado hasta que el proceso hijo
         termine.

   2. La jerarqu´a resultante se puede observar en la figura 6.2.
                ı
                                                         ´
         Se observa que el proceso padre es siempre el ultimo en terminar. Esto es
         debido a que la llamada al sistema wait, que hace que el proceso padre pase
         a estado bloqueado hasta que un proceso hijo termine, se encuentra dentro de
         un bucle que va a hacer que se llame tantas veces como procesos hijos cre´ .
                                                                                   o

                                                                   57
 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        58   100 Ejercicios resueltos de Sistemas Operativos - UJI
Figura 6.2: Jerarqu´a en anchura donde para cada proceso se indica la iteraci´ n del
                    ı                                                        o
bucle en la que se crea.


         Sin embargo, los procesos hijos acaban en cualquier orden dependiendo del
         retardo que cada uno realice con la orden sleep.

   3. La jerarqu´a resultante se puede observar en la figura 6.3.
                ı




                               @ibaumo
            ´
Figura 6.3: Arbol de procesos donde para cada proceso se indica la llamada a fork
responsable de su creaci´ n.
                        o

   4. La jerarqu´a resultante se puede observar en la figura 6.4.
                ı

   5. La jerarqu´a resultante se puede observar en la figura 6.5.
                ı

   6. La jerarqu´a resultante se puede observar en la figura 6.6. A continuaci´ n se
                ı                                                            o
      muestra un ejemplo del c´ digo con las llamadas correspondientes.
                                o
         #include          sys/types.h
         #include          sys/wait.h
         #include          unistd.h
         #include          stdio.h
         #include          stdlib.h

         #define L1 2
         #define L2 3

         int main (int argc, char ∗argv[]) {

             int cont1, cont2;
             pid t pid;

             for (cont2= 0; cont2 L2; cont2++) {
               for (cont1= 0; cont1 L1; cont1++) {
                 pid= fork();
                 if (pid== 0) break;


                                                                    58

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        59   100 Ejercicios resueltos de Sistemas Operativos - UJI
´
Figura 6.4: Arbol de procesos donde para cada proceso se indica la iteraci´ n en la
                                                                           o
que se crea y si realiza el cambio de imagen (aquellos que contienen ”ls”).




             ´                 @ibaumo
Figura 6.5: Arbol de procesos donde para cada uno se indica la iteraci´ n en la que
se crea y la llamada a fork responsable de su creaci´ n.
                                                    o
                                                                      o



                 }
                 if (pid!= 0) break;
             }

             printf (Soy el proceso de PID %d y mi padre tiene %d de PID.n,
                      getpid(), getppid());
             if (pid!= 0)
               for (cont1= 0; cont1 L1; cont1++)
                 printf (Fin del proceso de PID %d.n, wait (NULL));

             return 0;
         }


   7. La jerarqu´a resultante se puede observar en la figura 6.7. A continuaci´ n
                 ı                                                              o
      se muestra el c´ digo para que se produzcan las esperas solicitadas as´ como
                     o                                                       ı
      se informe de los tiempos correspondientes. Se˜ alar que todos los proce-
                                                         n
      sos hijos ejecutan la aplicaci´ n kcalc y que la ejecuci´ n de xload nunca se
                                    o                         o
      produce.


                                                                    59

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        60      100 Ejercicios resueltos de Sistemas Operativos - UJI
´
Figura 6.6: Arbol de procesos donde para cada uno se indica la iteraci´ n en la que
                                                                      o
se crea.

         #include          sys/types.h
         #include          sys/wait.h
         #include          unistd.h
         #include          stdio.h
         #include          stdlib.h
         #include          time.h

         int main (int argc, char ∗argv[]) {




                               @ibaumo
             int i, j;
             pid t pid, nuevo, nuevo1;
             time t ini, fin;

             ini= time(NULL);
             for (i= 0; i 2; i++){
               pid= getpid();
               for (j= 0; j i+2; j++){
                 nuevo= fork();
                 if(nuevo== 0){
                   break;
                   nuevo1= fork();
                   if(nuevo1== 0)
                     execlp (xload, xload, NULL);
                 }
               }
               if (pid!= getpid())
                 execlp (kcalc, kcalc, NULL);
             }

             for (i= 0; i 2; i++)
               for (j= 0; j i+2; j++){
                 wait(NULL);
                 printf (Tiempo en ejecuci´ n de kcalc: %ldn, time(NULL)-ini);
                                           o
               }

             printf (Tiempo total: %ldn, time(NULL)-ini);
             return 0;
         }




                                                                    60

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        61    100 Ejercicios resueltos de Sistemas Operativos - UJI
Figura 6.7: Jerarqu´a donde para cada proceso hijo se indica la iteraci´ n del bucle
                   ı                                                   o
en la que se crea.


   8. A continuaci´ n se muestra el trozo de c´ digo que habr´a que insertar en el
                  o                           o              ı
      programa del enunciado donde figura el comentario de /* completar aqu´ */.
                                                                              ı
         for (prof= 0; prof profundidad-1; prof++)
           if (fork()!= 0) /∗ jerarqu´a en profundidad ∗/
                                     ı
             break;

         /∗ if ((prof!= 0)  (prof %2== 0)) ∗/ /∗ ampliaci´n ∗/
                                                           o
         for (anch= 0; anch anchura-1; anch++)
           if (fork()== 0) /∗ jerarqu´a en anchura ∗/
                                      ı
             break;


   9.    for (cont1= 0; cont1 n; cont1++){
           pid= getpid();
           for(cont2= 0;cont2 cont1+2; cont2++){
             nuevo= fork();




                               @ibaumo
             if (nuevo == 0)
               break;
           }
           npid= getpid();
           if (npid== pid)
             break;
         }



 10. Para medir el tiempo habr´ que realizar dos llamadas a time(), una antes de
                                 a
     ejecutar prueba.exe y otra despu´ s. Restando los valores obtenidos calcu-
                                        e
     lamos el tiempo que ha transcurrido. Ya que el proceso hijo es quien va a
     realizar el cambio de imagen, la medici´ n de tiempo la debe realizar el pro-
                                               o
     ceso padre. El proceso padre no toma el valor inicial del tiempo correcto, que
     est´ inicializado a cero, ya que la linea inicio= time(); la ejecuta el proceso
        a
     hijo. La soluci´ n es que dicha l´nea la ejecute el proceso padre poni´ ndola,
                     o                ı                                      e
     por ejemplo, justo antes de la llamada a wait(NULL);.

 11. Si la aplicaci´ n kcalc est´ en alguna de las rutas almacenadas por la variable
                   o            a
     de entorno PATH, se producir´ el cambio de imagen en el proceso pasando
                                      a
     a ejecutarse la aplicaci´ n kcalc. En el caso de no encontrarse, la ejecuci´ n
                              o                                                  o
     del proceso continua imprimiendo el mensaje e intentar´ realizar el cambio
                                                                a
     de imagen con la aplicaci´ n xload. En el caso de tampoco encontrarla, el
                                  o
     proceso continua su ejecuci´ n imprimiendo un nuevo mensaje y finalizando.
                                   o
     A continuaci´ n se muestra el programa modificado tal y como se solicita en
                   o
     el enunciado.

                                                                    61

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        62   100 Ejercicios resueltos de Sistemas Operativos - UJI
#include          sys/types.h
      #include          sys/wait.h
      #include          unistd.h
      #include          stdio.h
      #include          stdlib.h


      int main (int argc, char ∗argv[]) {

          pid t pid kcalc, pid xload, pidfin;
          int num;

          pid kcalc= fork();
          if (pid kcalc== 0) {
            execlp (kcalc, kcalc, NULL);
            printf (No se encuentra la aplicaci´ n kcalcn);
                                                o
            exit (0);
          }

          pid xload= fork();
          if (pid xload== 0) {
            execlp (xload, xload, NULL);
            printf (No se encuentra la aplicaci´ n xloadn);
                                                o
            exit (0);
          }

          for (num= 0; num 2; num++) {
            pidfin= wait (NULL);
            if (pidfin== pid kcalc)
              printf (Ha terminado kcalcn);




                               @ibaumo
            else
              printf (Ha terminado xloadn);
          }

          return 0;
      }



12.   #include          sys/types.h
      #include          sys/wait.h
      #include          unistd.h
      #include          stdio.h
      #include          stdlib.h
      #include          time.h


      int main (int argc, char ∗argv[]) {

          pid t pid kcalc, pid xload, pidfin;
          int num;
          time t ini, fin;

          ini= time (NULL);

          pid kcalc= fork();
          if (pid kcalc== 0) {
            execlp (kcalc, kcalc, NULL);
            printf (No se encuentra la aplicaci´ n kcalcn);
                                                o
            exit (0);
          }

          pid xload= fork();


                                                                    62


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        63   100 Ejercicios resueltos de Sistemas Operativos - UJI
if (pid xload== 0) {
            execlp (xload, xload, NULL);
            printf (No se encuentra la aplicaci´ n xloadn);
                                                o
            exit (0);
          }

          for (num= 0; num 2; num++) {
            pidfin= wait (NULL);
            fin= time (NULL);
            if (pidfin== pid kcalc)
              printf (Ha terminado kcalc, %ld segundosn, fin-ini);
            else
              printf (Ha terminado xload, %ld segundosn, fin-ini);
          }
          fin= time (NULL);
          printf (Proceso padre, %ld segundosn, fin-ini);

          return 0;
      }


13.   #include          unistd.h
      #include          stdio.h
      #include          stdlib.h
      #include          sys/types.h
      #include          sys/wait.h

      #define MAXLON 100

      int main (int argc, char ∗argv[]) {




                               @ibaumo
          char cadena1[MAXLON], cadena2[MAXLON];
          int pos;
          pid t pid;

          printf (Introduce la cadena 1n); gets (cadena1);
          printf (Introduce la cadena 2n); gets (cadena2);

          pid= fork();
          if (pid!= 0) { /∗ proceso padre ∗/
            for (pos= 0; cadena1[pos]!= ’0’; pos++) {
              printf ( %c, cadena1[pos]);
              fflush (stdout);
              sleep (random() %3);
            }
            wait (NULL); /∗ espera a que termine el hijo ∗/
            printf (n);
          }
          else /∗ proceso hijo ∗/
            for (pos= 0; cadena2[pos]!= ’0’; pos++) {
              printf ( %c, cadena2[pos]);
              fflush (stdout);
              sleep (random() %3);
            }

          return 0;
      }


14.   #include stdio.h
      #include unistd.h
      #include stdlib.h


                                                                    63


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        64   100 Ejercicios resueltos de Sistemas Operativos - UJI
#include          string.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          stdbool.h

      int main (int argc, char ∗argv[]) {

          pid t nuevo;
          bool fin= false;
          char nombre[50], esperar[5];

          while (!fin) {
            printf (Nombre: ); scanf ( %s, nombre);
            if (strcmp(nombre, salir)!= 0) {
              printf (Esperar? ); scanf ( %s, esperar);
              nuevo= fork ();
              if (nuevo!= 0) { /∗ proceso padre ∗/
                if (strcmp (esperar, si)== 0)
                   while (nuevo!= wait (NULL));
                else
                   printf (PID del proceso hijo %dn, nuevo);
              } else { /∗ proceso hijo ∗/
                if (execlp (nombre, nombre, NULL)== -1)
                   printf (No se ha podido ejecutar. Variable PATH: %sn,
                           getenv (PATH));
                 exit(0);
              }
            }
            else
              fin= true;




                               @ibaumo
          }
          return 0;
      }



15.   #include          stdio.h
      #include          stdlib.h
      #include          unistd.h
      #include          sys/types.h
      #include          sys/wait.h

      int main (int argc, char ∗argv[]) {

          pid t nuevo;

          if (argc!= 3) {
            printf (Especfica dos numeros enteros.n);
            exit (0);
          }

          nuevo= fork ();
          if (nuevo!= 0) {
            nuevo= fork ();
            if (nuevo!= 0) {
              wait (NULL);
              wait (NULL);
              printf (Factoriales calculados.n);
            }
            else {
              execl (./factorial, ./factorial, argv[2], NULL);
              printf (No se encuentra la aplicacion factorialn);
              exit(0);


                                                                    64


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        65   100 Ejercicios resueltos de Sistemas Operativos - UJI
}
          }
          else {
            execl (./factorial, ./factorial, argv[1], NULL);
              printf (No se encuentra la aplicacion factorialn);
              exit(0);
            }

          return 0;
      }


16.   #include          stdio.h
      #include          stdlib.h
      #include          unistd.h
      #include          sys/types.h
      #include          sys/wait.h

      int main (int argc, char ∗argv[]) {

          pid t proceso, proc1;
          int param;

          if (argc 2) {
            printf (Indica los numeros de los que quieres calcular su factorial.n);
            exit(0);
          }

          for (param= 1; param argc; param++) {
            proceso= fork();




                               @ibaumo
            if (param== 1)
              proc1= proceso;
            if (proceso== 0) {
              execl (./factorial, ./factorial, argv[param], NULL);
              printf (No se encuentra la aplicacion factorialn);
              exit(0);
            }
          }

          for (param= 1; param argc; param++) {
            proceso= wait(NULL);
            if (proceso!= proc1)
              printf (Proceso de PID %d finalizadon, proceso);
          }

          printf (Factoriales calculados.n);
          return 0;
      }


17.   #include          stdio.h
      #include          stdlib.h
      #include          unistd.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          time.h


      int main (int argc, char ∗argv[]) {

          pid t pid;
          time t inicio, fin;


                                                                    65


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        66              100 Ejercicios resueltos de Sistemas Operativos - UJI
if (argc 2) {
            printf (Indica un programa a ejecutar.n);
            exit(0);
          }

          pid= fork();
          if (pid== 0) {
            execvp (argv[1], argv[1]);
            printf (No se encuentra la aplicacion %sn, argv[1]);
            exit(0);
          }
          inicio= time (NULL);
          wait (NULL);
          fin= time (NULL);

          printf (Duraci´ n: %ld segundosn, fin-inicio);
                         o
          return 0;
      }




          E/S D2
          E/S D1                                                                        A1        A2
          CPU             IR        A1        A2         IS         IR        IS        B1        B2        IH1       IR    B3      B4

          E/S D2                                                                                  A1        A2        A3    A4      A5
18.       E/S D1                                                                                                                    B1
          CPU             IR        A1        A2        A3          IR        IS        IS        B5        IR        IS    IS      N




                               @ibaumo
          E/S D2
          E/S D1
          CPU           IH1         IR        IH2       B1          IR        IS        IS        A1        IR        IS    IS




          E/S                                                                                A1        A2     A3
          CPU        IR        A1        A2       A3        IS       IR            IS        B1        B2     B3       IH    IR

          E/S                                                                                          A1
19.       CPU       B4         B5        B6       IR       A1        A2            IS        IS        IR        IH    B7    B8

          E/S                                     B1
          CPU        IS        IR        IS       A1        IH           IS        IR        IS        B1        IS    IS




          E/S                                                                                                               A1
          CPU       IR         A1      A2        A3        IR        A4        A5            A6    IR         IS       IS   B1

          E/S                                                                  B1            B2    B3        B4        B5    B6
20.       CPU       IH         IR      B2         IS       IR        IS        A1            A2    IR        IS        IS    N

          E/S
          CPU       IH         IR      B1        B2        IR        B3            IS        IS

                                                                     66



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7                        67                                  100 Ejercicios resueltos de Sistemas Operativos - UJI
E/S                                                                        A1        A2        A3        A4        A5        A6
        CPU          IR        A1       A2          A3         IR        IS        B1        B2        IR        B3        B4        B5

        E/S         A7         A8       A9        A10                                        C1        C2        C3        C4
21.     CPU         IR         C1       C2        C3           IH        IR        IS        A1        IR        A2        A3        IH

        E/S
        CPU          IR        C1         IS        B6         IR        IS        A4        IS

        E/S                                                                                 A1
        CPU         IR         A1      A2        A3           IR        IS        IS        B1     IH       IR        B2        B3

        E/S                                                 A1
22.     CPU         IR         A1       IS        IS        IR          IH        B4        IS     IR        IS       A1        IS

        E/S
        CPU         IR         IS

        E/S
        CPU          IR        A1         A2         A3            IR    A4            A5         A6        IR        B1        B2        IS

        E/S         B1                                                                                                                    B1
23.     CPU         IR         IH         A7         A8            IR    A9            A10        A11       IR        B1        IS        A12

        E/S
        CPU          IH        IR       A13         A14            IR        IS        B1         IS




                               @ibaumo
        E/S D2                                                                                                                  B1        B2
        E/S D1                                                      A1        A2        A3        A4        A5        A6        A7        A8
        CPU               IR         A1        IS        IS         IR        B1        B2        IS        IR        IS        C1        C2

        E/S D2
24.     E/S D1
        CPU             IH1          IH2       IR      C3           IR        B1        B2        B3        IR        B4        B5        B6

        E/S D2
        E/S D1
        CPU               IR         A1        IS        IS         IR        C4        IS        IS        IR        B7        IS        IS

        E/S
        CPU          IR        A1          A2          A3          A4        IR        A5        A6     A7            A8         IR            B1

        E/S                                B1                                          C1        C2     C3        C4            C5         C6
        CPU         B2          IS         C1          IR          IH        IS        A9        A10    IR        A11           A12        A13
25.
        E/S
        CPU          IH        IR          B1          B2          B3        IS        IR        C1     C2            C3         C4            IR

        E/S
        CPU          IS        A14         A15         IS

26.   #include          unistd.h
      #include          stdlib.h
      #include          stdio.h
      #include          pthread.h


                                                                        67

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7                       68                                       100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗ factorial (void ∗ dato) {

          long long int resultado= 1;
          int num, n= atoi((char ∗) dato);

          for (num= 2; num= n; num++) {
            resultado= resultado∗ num;
            printf (Factorial de %d, resultado parcial %lldn, n, resultado);
            sleep (random() %3);
          }
          printf (El factorial de %d es %lldn, n, resultado);
          pthread exit(NULL);
      }

      int main (int argc, char ∗argv[]) {

          pthread t hilo1, hilo2;

          if (argc!= 3) {
            printf (Indica dos numeros enteros.n);
            exit(0);
          }

          pthread create (hilo1, NULL, factorial, (void ∗) argv[1]);
          pthread create (hilo2, NULL, factorial, (void ∗) argv[2]);

          pthread join (hilo1, NULL);
          pthread join (hilo2, NULL);

          printf (Factoriales calculadosn);




                               @ibaumo
          return 0;
      }



27.   #include          unistd.h
      #include          stdlib.h
      #include          stdio.h
      #include          pthread.h

      void ∗ factorial (void ∗ dato) {

          long long int resultado= 1;
          int num, n= atoi((char ∗) dato);

          for (num= 2; num= n; num++) {
            resultado= resultado∗ num;
            printf (Factorial de %d, resultado parcial %lldn, n, resultado);
            sleep (random() %3);
          }
          printf (El factorial de %d es %lldn, n, resultado);
          pthread exit (NULL);
      }

      int main (int argc, char ∗argv[]) {

          pthread t hilo[argc-1];
          int param;

          if (argc 2) {
            printf (Indica los numeros de los que quieres obtener su factorial.n);
            exit (0);


                                                                    68



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        69             100 Ejercicios resueltos de Sistemas Operativos - UJI
}

          for (param= 0; param argc-1; param++)
            pthread create (hilo[param], NULL, factorial,
                            (void ∗) argv[param+1]);

          for (param= 0; param argc-1; param++) {
            pthread join (hilo[param], NULL);
            printf (Hilo %d finalizadon, param+1);
          }

          printf (Factoriales calculadosn);
          return 0;
      }


28.   #include          stdlib.h
      #include          stdio.h
      #include          pthread.h
      #include          unistd.h

      #define MAXLON 100

      void ∗imprimecadena (void ∗dato) {

          int pos;
          char ∗cadena= (char ∗) dato;

          for (pos= 0; cadena[pos]!= ’0’; pos++) {
            printf ( %c, cadena[pos]);




                               @ibaumo
            fflush (stdout);
            sleep (random() %3);
          }
          pthread exit(NULL);
      }

      int main (int argc, char ∗argv[]) {

          pthread t hilo1, hilo2;
          char cadena1[MAXLON], cadena2[MAXLON];

          printf (Introduce la cadena 1n); gets (cadena1);
          printf (Introduce la cadena 2n); gets (cadena2);

          pthread create (hilo1, NULL, imprimecadena, (void ∗) cadena1);
          pthread create (hilo2, NULL, imprimecadena, (void ∗) cadena2);

          pthread join (hilo1, NULL);
          pthread join (hilo2, NULL);

          printf (n);
          return 0;
      }


29.   #include          unistd.h
      #include          stdlib.h
      #include          stdio.h
      #include          pthread.h
      #include          sys/types.h
      #include          sys/stat.h
      #include          fcntl.h


                                                                    69


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        70   100 Ejercicios resueltos de Sistemas Operativos - UJI
#define MAXLON 1000

      void ∗cuenta (void ∗dato) {

          int pos, cont= 0, leidos;
          char ∗nombre= (char ∗) dato, cadena[MAXLON];
          int fd;

          fd= open (nombre, O RDONLY);
          while ((leidos= read (fd, cadena, MAXLON))!= 0)
            for (pos= 0; pos leidos; pos++)
              if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’))
                cont++;
          printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn, nombre, cont);
          close (fd);
          pthread exit (NULL);
      }

      int main (int argc, char ∗argv[]) {

          pthread t hilo;

          if (argc!= 2) {
            printf (Indica el nombre de un fichero.n);
            exit(0);
          }
          pthread create (hilo, NULL, cuenta, (void ∗) argv[1]);
          pthread join     (hilo, NULL);

          return 0;




                               @ibaumo
      }



30.   #include          unistd.h
      #include          stdlib.h
      #include          stdio.h
      #include          pthread.h
      #include          sys/types.h
      #include          sys/stat.h
      #include          fcntl.h

      #define MAXLON 1000

      void ∗cuenta (void ∗dato) {

          int pos, cont= 0, leidos;
          char ∗nombre= (char ∗) dato, cadena[MAXLON];
          int fd;

          fd= open (nombre, O RDONLY);
          while ((leidos= read (fd, cadena, MAXLON))!= 0)
            for (pos= 0; pos leidos; pos++)
              if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’))
                cont++;
          printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn, nombre, cont);
          close (fd);
          pthread exit (NULL);
      }




                                                                    70



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        71      100 Ejercicios resueltos de Sistemas Operativos - UJI
int main (int argc, char ∗argv[]) {

          pthread t hilo[argc-1];
          int param;

          if (argc 2) {
            printf (Indica el nombre de uno o varios ficheros.n);
            exit(0);
          }

          for (param= 0; param argc-1; param++)
            pthread create (hilo[param], NULL, cuenta,
                            (void ∗) argv[param+1]);

          for (param= 0; param argc-1; param++)
            pthread join(hilo[param], NULL);

          return 0;
      }



31.   #include          unistd.h
      #include          stdlib.h
      #include          stdio.h
      #include          pthread.h
      #include          sys/types.h
      #include          sys/stat.h
      #include          fcntl.h

      #define MAXLON 1000




                               @ibaumo
      typedef struct {
        char ∗nombre;
        int cont;
      } info;

      void ∗cuenta (void ∗dato) {

          int pos, cont= 0, leidos;
          info ∗misdatos= (info ∗) dato;
          char cadena[MAXLON];
          int fd;

          fd= open (misdatos-nombre, O RDONLY);
          while ((leidos= read (fd, cadena, MAXLON))!= 0)
            for (pos= 0; pos leidos; pos++)
              if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’)) cont++;
          misdatos-cont= cont;
          close (fd);
          pthread exit (NULL);
      }


      int main (int argc, char ∗argv[]) {

          pthread t vectorhilos[argc-1];
          info vectordatos[argc-1];
          int param;

          if (argc 2) {
            printf (Indica el nombre de uno o varios ficheros.n); exit(0);
          }


                                                                    71


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        72    100 Ejercicios resueltos de Sistemas Operativos - UJI
for (param= 0; param argc-1; param++) {
            vectordatos[param].nombre= argv[param+1];
            vectordatos[param].cont=   0;
            pthread create (vectorhilos[param], NULL, cuenta,
                            (void ∗) vectordatos[param]);
          }

          for (param= 0; param argc-1; param++)
            pthread join (vectorhilos[param], NULL);

          for (param= 0; param argc-1; param++)
            printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn,
                    vectordatos[param].nombre, vectordatos[param].cont);

          return 0;
      }



32.   #include          unistd.h
      #include          stdlib.h
      #include          stdio.h
      #include          pthread.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          sys/stat.h
      #include          fcntl.h

      #define K 50

      typedef struct {




                               @ibaumo
        char ∗nombre;
        int inicio;
        int encontrados;
      } info;

      void ∗busca (void ∗datos) {

          int pos, cont= 0, leidos, fd;
          info∗ datoshilo= (info ∗) datos;
          char cadena[K];

          sleep (random() %3);
          fd= open (datoshilo-nombre, O RDONLY);
          lseek (fd, datoshilo-inicio, SEEK SET);
          leidos= read (fd, cadena, K);
          for (pos= 0; pos leidos; pos++)
            if (cadena[pos]== ’ ’)
              cont++;
          close (fd);
          datoshilo-encontrados= cont;
          pthread exit (NULL);
      }

      void cuentaEspacios (char ∗nombre){

          int longitud, pos, nHilos, fd, total= 0;
          pthread t ∗vectorhilos;
          info ∗vectordatos;

          /∗ averigua la longitud del fichero ∗/
          fd= open (nombre, O RDONLY);


                                                                    72



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        73   100 Ejercicios resueltos de Sistemas Operativos - UJI
longitud= lseek (fd, 0, SEEK END);
          close (fd);

          /∗ determina el numero de hilos a crear ∗/
          nHilos= longitud/K;
          if ((longitud % K)!= 0)
            nHilos++;
          vectorhilos= (pthread t ∗) malloc (nHilos∗sizeof(pthread t));
          vectordatos=       (info ∗) malloc (nHilos∗sizeof(info));

          for (pos= 0; pos nHilos; pos++) {
            vectordatos[pos].nombre= nombre;
            vectordatos[pos].inicio= pos∗ K;
            vectordatos[pos].encontrados= 0;
            pthread create (vectorhilos[pos], NULL, busca,
                            (void ∗) vectordatos[pos]);
          }

          for (pos= 0; pos nHilos; pos++) {
            pthread join (vectorhilos[pos], NULL);
            total+= vectordatos[pos].encontrados;
          }

          printf (Fichero %s: %d espacios en blanco encontradosn, nombre, total);
          free (vectorhilos);
          free (vectordatos);
      }

      int main (int argc, char ∗argv[]) {




                               @ibaumo
          int numfich;

          for (numfich= 1; numfich argc; numfich++)
            if (fork()== 0) {
              cuentaEspacios (argv[numfich]);
              exit(0);
            }

          for (numfich= 1; numfich argc; numfich++)
            wait(NULL);

          return 0;
      }



33.   #include          stdio.h
      #include          stdlib.h
      #include          unistd.h
      #include          time.h
      #include          sys/types.h
      #include          sys/wait.h

      int main (int argc, char ∗argv[]){

          int tubo[2];
          time t ini= time(NULL), fin;

          if (fork()== 0){
            pipe (tubo);
            if (fork()== 0){
              dup2   (tubo[1],STDOUT FILENO);
              close (tubo[0]);


                                                                    73


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        74     100 Ejercicios resueltos de Sistemas Operativos - UJI
close (tubo[1]);
             execlp (ls,ls,NULL);
           }else{
             dup2   (tubo[0],STDIN FILENO);
             close (tubo[0]);
             close (tubo[1]);
             execlp (wc,wc,-l,NULL);
           }
         } else {
           wait (NULL);
           fin= time (NULL);
           printf (Tiempo invertido: %ld segundosn, fin-ini);
         }

         return 0;
     }



34. El proceso que ejecuta el comando ls redirige la salida estandar utilizando el
    descriptor de lectura de la tuber´a, en lugar del de escritura. Esto produce un
                                     ı
    error. A su vez, el proceso que ejecuta la orden sort redirige el descriptor de
    lectura estandard utilizando el descriptor de escritura de la tuber´a. Tambi´ n
                                                                        ı        e
    produce un error.
     Soluci´ n, cambiar las l´neas siguientes:
           o                 ı

     dup2(tubo[1], STDIN_FILENO); por dup2(tubo[0], STDIN_FILENO);




                               @ibaumo
     dup2(tubo[0], STDOUT_FILENO); por dup2(tubo[1], STDOUT_FILENO);


     Y adem´ s, las dos llamadas a close del proceso que va a cambiar su imagen
             a
     con el comando sort, ponerlas entre dup2 y execlp para evitar que, cuando
        ı          ı                                                  ´
     vac´e la tuber´a habiendo terminado el ls, se bloquee por tener el mismo el
     descriptor de escritura de la tuber´a abierto cuando se produce el cambio de
                                        ı
     imagen.

35. El problema que se produce es debido a que el proceso inicial tiene acceso
    a la tuber´a y no cierra el descriptor de escritura. En consecuencia, el pro-
              ı
    ceso que cambia su imagen al comando wc (que lee de la tuber´a) pasa a
                                                                      ı
    bloqueado al vaciarla, a´ n cuando haya terminado el que cambia su imagen
                             u
    al comando ls (que es el que realmente escribe en la tuber´a).
                                                               ı
     Para solucionarlo, por ejemplo, y ya que el proceso inicial no va a utilizar la
     tuber´a, mover la orden pipe justo despu´ s del primer if manteniendo as´ el
          ı                                  e                                  ı
     acceso a los otros dos procesos pero evitando que el proceso inicial tenga
     acceso a la tuber´a.
                      ı

36. El programa pretende realizar el sort de un fichero. Para ello escribe, en
    primer lugar, el contenido del fichero en una tuber´a. Es en este punto donde
                                                       ı
    el proceso puede pasar a estado de bloqueo si se llena la tuber´a, no saliendo
                                                                    ı
    de este estado al no haber ning´ n proceso que lea de ella y, en consecuencia,
                                   u
    la vac´e. En el caso de que la tuber´a tuviese capacidad para almacenar el
          ı                               ı

                                                                    74


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        75   100 Ejercicios resueltos de Sistemas Operativos - UJI
contenido completo del fichero, la ejecuci´ n continuar´a y se mostrar´a el
                                                   o           ı           ı
      resultado de ejecutar la orden sort sobre el contenido del fichero.

37. El flujo de informaci´ n de la tuber´a se realiza desde el proceso ls, que act´ a
                        o              ı                                         u
    como proceso hijo y escribe en la tuber´a, hacia el proceso wc que act´ a
                                               ı                                 u
    como proceso padre y lee de la tuber´a.
                                          ı
      Si la cantidad total de informaci´ n escrita en la tuber´a, resultado de la ejecu-
                                       o                      ı
      ci´ n del comando ls, es inferior al tama˜ o de la tuber´a, y s´ lo en este caso,
        o                                        n              ı      o
      no habr´ problema alguno y se podr´ observar el resultado de la ejecuci´ n
               a                             a                                        o
      de ls | wc -l.
      Sin embargo, en cuanto la cantidad de informaci´ n superase la capacidad de
                                                        o
      la tuber´a, entonces el proceso que escribe pasar´a al estado de bloqueado,
              ı                                          ı
                        ı           ´
      del cual no saldr´a ya que el unico proceso que podr´a leer datos de la tuber´a,
                                                           ı                       ı
      el proceso padre, est´ tambi´ n en estado de bloqueo como consecuencia de
                            a       e
      la ejecuci´ n de la orden wait(NULL).
                o
38.   #include          stdio.h
      #include          stdlib.h
      #include          sys/types.h
      #include          wait.h
      #include          unistd.h
      #include          sys/stat.h
      #include          fcntl.h




                               @ibaumo
      int main (int argc, char ∗argv[]) {

         int tubo1[2], tubo2[2], mifichero;

         pipe(tubo1);
         pipe(tubo2);

         if (fork()== 0) {
           if (fork()== 0) {
             dup2 (tubo1[1], STDOUT FILENO);
             close (tubo1[0]);
             close (tubo2[0]);
             close (tubo2[1]);
             close (tubo1[1]);
             execlp (paste, paste, argv[1], argv[2], NULL);
           } else {
             dup2 (tubo1[0], STDIN FILENO);
             dup2 (tubo2[1], STDOUT FILENO);
             close (tubo1[1]);
             close (tubo2[0]);
             close (tubo1[0]);
             close (tubo2[1]);
             execlp (sort, sort, NULL);
           }
         } else {
           dup2 (tubo2[0], STDIN FILENO);
           close (tubo1[0]);
           close (tubo1[1]);
           close (tubo2[1]);
           close (tubo2[0]);
           mifichero= open(argv[3], O WRONLY|O CREAT);
           dup2 (mifichero, STDOUT FILENO);


                                                                    75

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        76   100 Ejercicios resueltos de Sistemas Operativos - UJI
close (mifichero);
              execlp (nl, nl, NULL);
          }

          return 0;
      }


39.   #include          stdio.h
      #include          stdlib.h
      #include          sys/types.h
      #include          wait.h
      #include          unistd.h
      #include          sys/stat.h
      #include          fcntl.h

      int main (int argc, char ∗argv[]) {

          int tubo1[2], mifichero;

          pipe(tubo1);

          if (fork()== 0) {
            dup2 (tubo1[1], STDOUT FILENO);
            close (tubo1[0]);
            close (tubo1[1]);
            execlp (grep, grep, argv[1], argv[2], NULL);
          } else
            if (fork()== 0) {
              dup2 (tubo1[1], STDOUT FILENO);




                               @ibaumo
              close (tubo1[0]);
              close (tubo1[1]);
              execlp (grep, grep, argv[1], argv[3], NULL);
            } else {
              dup2 (tubo1[0], STDIN FILENO);
              close (tubo1[0]);
              close (tubo1[1]);
              mifichero= creat(argv[4], 00644);
              dup2 (mifichero, STDOUT FILENO);
              close (mifichero);
              execlp (wc, wc, -m, NULL);
            }

          return 0;
      }


40.   #include          stdio.h
      #include          stdlib.h
      #include          sys/types.h
      #include          wait.h
      #include          unistd.h
      #include          string.h
      #include          sys/stat.h
      #include          fcntl.h

      #define MAXLON 1000

      int main (int argc, char ∗argv[]) {

          int tubo1[2], tubo2[2], fd;
          int nlinea;


                                                                    76


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        77   100 Ejercicios resueltos de Sistemas Operativos - UJI
FILE ∗fich;
         char linea[MAXLON], cad1[MAXLON], cad2[MAXLON];

         pipe(tubo1);
         pipe(tubo2);

         if (fork()!= 0) {
           if (fork()!= 0) { /∗ Separar lineas pares e impares ∗/
             close (tubo1[0]);
             close (tubo2[0]);
             if (!(fich= fopen (argv[1],r))) {
               printf (Error al abrir el fichero %sn,argv[1]);
               exit(0);
             }
             nlinea= 1;
             while (fgets (linea, MAXLON, fich)) {
               if (nlinea %2== 1) /∗ Impar ∗/
                 write (tubo1[1], linea, strlen (linea));
               else /∗ Par ∗/
                 write (tubo2[1], linea, strlen (linea));
               nlinea++;
             }
             fclose (fich);
             close (tubo1[1]);
             close (tubo2[1]);
             wait (NULL);
             wait (NULL);
           } else { /∗ impares ∗/
             dup2 (tubo1[0], STDIN FILENO);
             close (tubo1[1]);




                               @ibaumo
             close (tubo2[1]);
             close (tubo1[0]);
             close (tubo2[0]);
             sprintf (cad1,  %s.txt, argv[2]);
             fd= creat(cad1,00644);
             dup2 (fd, STDOUT FILENO);
             close (fd);
             execlp (grep, grep, argv[2], NULL);
           }
         } else { /∗ pares ∗/
             dup2 (tubo2[0], STDIN FILENO);
             close (tubo1[1]);
             close (tubo2[1]);
             close (tubo1[0]);
             close (tubo2[0]);
             sprintf (cad2,  %s.txt, argv[3]);
             fd= creat (cad2,00644);
             dup2 (fd, STDOUT FILENO);
             close (fd);
             execlp (grep, grep, argv[3], NULL);
         }
         return 0;
     }



41. Es necesario que las tareas 1 y 4 las hagan procesos distintos que se ejecuten
    en paralelo, ya que, si las realiza el mismo proceso, la tarea 4, que es la que
    vaciar´a la tuber´a 3, nunca empezar´ mientras no se termine la tarea 1, lo
          ı          ı                      a
    que puede producir que la tuber´a 3 se llene y, en consecuencia, los procesos
                                      ı
    que ejecutan el comando grep se bloqueen al escribir sobre la tuber´a llena,
                                                                           ı

                                                                    77


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        78   100 Ejercicios resueltos de Sistemas Operativos - UJI
dejando de leer de las tuber´as 1 y 2, y produciendo a su vez que las tuber´as
                             ı                                             ı
1 y 2 puedan llenarse y tambi´ n el bloqueo del proceso que ejecuta la tarea
                                e
1 al intentar escribir sobre una tuber´a llena.
                                      ı
#include       stdio.h
#include       sys/types.h
#include       wait.h
#include       unistd.h
#include       string.h
#include       stdlib.h

#define MAX 1000

int main(int argc, char ∗argv[]) {

  int      nlinea;
  FILE     ∗fichero;
  char     linea[MAX];
  int      tubo1[2], tubo2[2], tubo3[2];

  if (argc!=4) {
    printf(Error en el n´ mero de parametrosn);
                         u
    exit(1);
  }

  pipe(tubo1);
  pipe(tubo2);
  pipe(tubo3);




                               @ibaumo
  if (fork()!=0) {
    if (fork()!= 0) {
      if (fork()!= 0) { // tarea 4
        dup2(tubo3[0], STDIN FILENO);
        close (tubo1[0]);
        close (tubo1[1]);
        close (tubo2[0]);
        close (tubo2[1]);
        close (tubo3[0]);
        close (tubo3[1]);
        execlp (sort, sort, NULL);
      } else { // tarea 3
        dup2(tubo2[0], STDIN FILENO);
        dup2(tubo3[1], STDOUT FILENO);
        close (tubo1[0]);
        close (tubo1[1]);
        close (tubo2[0]);
        close (tubo2[1]);
        close (tubo3[0]);
        close (tubo3[1]);
        execlp (grep, grep, argv[3], NULL);
      }
    } else { //tarea 2
      dup2(tubo1[0], STDIN FILENO);
      dup2(tubo3[1], STDOUT FILENO);
      close (tubo1[0]);
      close (tubo1[1]);
      close (tubo2[0]);
      close (tubo2[1]);
      close (tubo3[0]);
      close (tubo3[1]);
      execlp (grep, grep, argv[2], NULL);
    }


                                                            78

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   79   100 Ejercicios resueltos de Sistemas Operativos - UJI
} else { //tarea 1
            close (tubo1[0]);
            close (tubo2[0]);
            close (tubo3[0]);
            close (tubo3[1]);
            if (!(fichero= fopen(argv[1],r))) {
              printf(Error al abrir el fichero %sn,argv[1]);
              exit(2);
            }
            nlinea=0;
            while (fgets(linea,MAX,fichero)) {
              if (nlinea %2==0)
                write(tubo1[1],linea,strlen(linea));
              else
                write(tubo2[1],linea,strlen(linea));
              nlinea++;
            }
            fclose(fichero);
            close (tubo1[1]);
            close (tubo2[1]);
          }

          return 0;
      }


42. No se da situaci´ n de interbloqueo, todos los procesos acabar´ n las secuen-
                     o                                             a
    cias de c´ digo. La salida por pantalla es la siguiente: 34125. Valor final de
              o
    los sem´ foros: los cuatro sem´ foros est´ n a cero.
            a                      a         a




                               @ibaumo
43. Ocurre situaci´ n de interbloqueo siempre. En el c´ digo A, el proceso se
                   o                                    o
    bloquea en la llamada al segundo sem wait(s2) mientras que, en el c´ digo
                                                                        o
    B, el proceso se bloquea en la llamada al segundo sem wait(s1).
      Hasta alcanzar el punto de interbloqueo, las posibles salidas son 2. Inicial-
      mente aparecen las cadenas A1 y B1, que pueden salir combinadas de cual-
                                     ´       ´        ´
      quier manera, es decir, A1B1 o B1A1 o AB11 o BA11. Despu´ s, siempre
                                                                      e
      saldr´ lo mismo: B2B3A2.
           a
44.   #include          unistd.h
      #include          stdlib.h
      #include          stdio.h
      #include          pthread.h
      #include          sys/types.h
      #include          sys/stat.h
      #include          fcntl.h
      #include          semaphore.h

      #define MAXLON 1000
      int cuenta blancos= 0;

      sem t blancos;

      typedef struct {
        char∗ nombre;
        int cont;
      } info;




                                                                    79


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        80   100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗cuenta (void ∗dato) {

          int pos, cont= 0, leidos;
          info ∗misdatos= (info ∗) dato;
          char cadena[MAXLON];
          int fd;

          fd= open (misdatos-nombre, O RDONLY);
          while ((leidos= read (fd, cadena, MAXLON))!= 0)
            for (pos= 0; pos leidos; pos++)
              if (cadena[pos]==’ ’) cont++;
          misdatos-cont= cont;
          sem wait (blancos);
          cuenta blancos+= cont;
          sem post (blancos);
          close (fd);
          pthread exit (NULL);
      }

      int main (int argc, char ∗argv[]) {

          pthread t hilo[argc-1];
          info datos[argc-1];
          int numfich;

          if (argc 2) {
            printf (Indica el nombre de uno o varios ficheros.n);
            exit(0);
          }




                               @ibaumo
          sem init (blancos, 0, 1);

          for (numfich= 0; numfich argc-1; numfich++) {
            datos[numfich].nombre= argv[numfich+1];
            datos[numfich].cont=   0;
            pthread create (hilo[numfich], NULL, cuenta,
                            (void ∗) datos[numfich]);
          }

          for (numfich= 0; numfich argc-1; numfich++)
            pthread join (hilo[numfich], NULL);

          for (numfich= 0; numfich argc-1; numfich++)
            printf (Fichero %s: %d espacios en blanco encontradosn,
                    datos[numfich].nombre, datos[numfich].cont);

          printf (Total de espacios en blanco: %dn, cuenta blancos);
          sem destroy (blancos);

          return 0;
      }



45.   #include          stdio.h
      #include          stdlib.h
      #include          time.h
      #include          unistd.h
      #include          pthread.h
      #include          semaphore.h

      sem t s1, s2, s3, s4, s5, s6;


                                                                    80



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        81   100 Ejercicios resueltos de Sistemas Operativos - UJI
void escribe (char ∗dato) {

    int num;

    for(num=         0; num 5; num++){
      printf         ( %sn,dato);
      fflush         (stdout);
      sleep          (random() %3);
    }
}

void ∗A (void ∗p){

    escribe (a1);
    sem post (s1);
    sem wait (s2);
    escribe (a2);
    sem post (s4);
    sem wait (s5);
    escribe (a3);
    sem post (s6);
    pthread exit (NULL);
}

void ∗B (void ∗p){

    escribe ( b1);
    sem post (s2);
    escribe ( b2);
    sem post (s3);




                                 @ibaumo
    sem wait (s4);
    escribe ( b3);
    sem wait (s6);
    sem wait (s6);
    escribe ( b4);
    pthread exit (NULL);
}

void ∗C (void ∗p){

    sem wait (s1);
    escribe ( c1);
    sem wait (s3);
    escribe ( c2);
    sem post (s5);
    escribe ( c3);
    sem post (s6);
    pthread exit (NULL);
}

int main (int argc, char ∗argv[]) {

    pthread t th1, th2, th3;

    sem init (s1,               0, 0);
    sem init (s2,               0, 0);
    sem init (s3,               0, 0);
    sem init (s4,               0, 0);
    sem init (s5,               0, 0);
    sem init (s6,               0, 0);
    pthread create               (th1, NULL, A, NULL);



                                                              81



    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   82   100 Ejercicios resueltos de Sistemas Operativos - UJI
pthread create (th2, NULL, B, NULL);
          pthread create (th3, NULL, C, NULL);
          pthread join (th1, NULL);
          pthread join (th2, NULL);
          pthread join (th3, NULL);
          sem destroy (s1);
          sem destroy (s2);
          sem destroy (s3);
          sem destroy (s4);
          sem destroy (s5);
          sem destroy (s6);

          return 0;
      }



46.   #include          stdio.h
      #include          stdlib.h
      #include          time.h
      #include          unistd.h
      #include          pthread.h
      #include          semaphore.h

      #define MAX 6

      sem t A, B, C;

      void ∗escribirA (void ∗nada){

          int num;




                               @ibaumo
          for (num= 0; num MAX; num++){
            sem wait (A);
            printf   (A);
            fflush   (stdout);
            sem post (B);
            sleep    (random() %3);
          }
          pthread exit (NULL);
      }

      void ∗escribirB (void ∗nada){

          int num;

          for (num= 0; num MAX; num++){
            sem wait (B);
            printf   (B);
            fflush   (stdout);
            sem post (C);
            sleep    (random() %2);
          }
          pthread exit (NULL);
      }

      void ∗escribirC (void ∗nada){

          int num;

          for (num= 0; num MAX; num++){
            sem wait (C);
            printf   (C);


                                                                    82


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        83   100 Ejercicios resueltos de Sistemas Operativos - UJI
fflush   (stdout);
             sem post (A);
             sleep    (random() %2);
         }
         pthread exit (NULL);
     }

     int main (int argc, char ∗argv[]) {

         pthread t th1, th2, th3;
         srandom(time(NULL));
         sem init (A, 0, 1); /∗ habilitado ∗/
         sem init (B, 0, 0); /∗ no habilitado ∗/
         sem init (C, 0, 0); /∗ no habilitado ∗/
         pthread create (th1, NULL, escribirA, NULL);
         pthread create (th2, NULL, escribirB, NULL);
         pthread create (th3, NULL, escribirC, NULL);
         pthread join (th1, NULL);
         pthread join (th2, NULL);
         pthread join (th3, NULL);
         sem destroy (A);
         sem destroy (B);
         sem destroy (C);

         return 0;
     }


47. Estos son los posibles valores de num as´ como los diferentes estados de los
                                            ı
    hilos:



                               @ibaumo
               num es 13, incementa termina, decrementa se bloquea en sem wait(sem2)
               con i a cero.
               num es 12, incrementa termina, decrementa se bloquea en sem wait(sem2)
               con i a uno.
               num es 11, incrementa termina, decrementa se bloquea en sem wait(sem2)
               con i a dos.
               num es 10, incrementa termina, decrementa se bloquea en sem wait(sem1)
               a continuaci´ n del bucle.
                           o
48. Utilizando dos sem´ foros, sA y sB, con sA a cero y sB a uno, esta es la
                      a
    soluci´ n:
          o
     void *escribirA (void *p) {                                    void *escribirB (void *p) {
       int i;                                                         int i;

         for (i= 0; i 5; i++) {                                         for (i= 0;i 5; i++) {
           sem_wait(sA);                                                  sem_wait(sB);
           printf (A);                                                   printf (B);
           fflush(NULL);                                                   fflush(NULL);
           sleep(random()%2);                                              sleep(random()%2);
           sem_post(sB);                                                  sem_post(sA);
         }                                                               }
         pthread_exit(NULL);                                             pthread_exit(NULL);
     }                                                              }


49. Los tres hilos se van a quedar bloqueados:

                                                                    83


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7              84                 100 Ejercicios resueltos de Sistemas Operativos - UJI
escribirA queda bloqueado en el sem wait(s1) con i = 2.
               escribirB queda bloqueado en el primer sem wait(s2) con j = 2.
               escribirC queda bloqueado en el primer sem wait(s3) con k = 1.
50.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          stdbool.h

      #define MAX 10
      #define FIN -1

      int buffer[MAX];
      sem t huecos, elementos;

      int generar dato (void) { return random() %256;}
      int numero aleatorio(void) { return random() %100;}

      void ∗productor (void ∗p) {

          int pos productor= 0;
          int num, dato, n;

          n= numero aleatorio();
          printf (Productor con %d datosn, n);
          for(num= 0; num n; num++) {




                               @ibaumo
            dato= generar dato();
            sem wait (huecos);
            buffer[pos productor]= dato;
            pos productor= (pos productor+ 1) %MAX;
            sem post (elementos);
          }
          sem wait (huecos);
          buffer[pos productor]= FIN;
          sem post (elementos);

          pthread exit (NULL);
      }

      void ∗consumidor(void ∗p){

          int pos consumidor= 0, dato;
          bool continuar= true;

          while (continuar) {
            sem wait (elementos);
            dato= buffer[pos consumidor];
            sem post (huecos);
            if (dato== FIN)
              continuar= false;
            else {
              printf (Numero aleatorio: %dn, dato);
              pos consumidor= (pos consumidor+1) %MAX;
            }
          }

          pthread exit (NULL);
      }



                                                                    84

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        85   100 Ejercicios resueltos de Sistemas Operativos - UJI
int main (int argc, char ∗argv[]) {

          pthread t hiloproductor, hiloconsumidor;

          sem init (elementos, 0, 0);
          sem init (huecos,    0, MAX);

          pthread create (hiloproductor, NULL, productor, NULL);
          pthread create (hiloconsumidor, NULL, consumidor, NULL);

          pthread join (hiloproductor, NULL);
          pthread join (hiloconsumidor, NULL);

          sem destroy (huecos);
          sem destroy (elementos);

          return 0;
      }



51.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          stdbool.h

      #define MAX 10
      #define FIN -1
      #define NUMPROD 3




                               @ibaumo
      int buffer[MAX];
      int pos productor= 0;
      sem t huecos, elementos, pos prod;

      int generar dato     (void) { return random() %256;}
      int numero aleatorio (void) { return random() %100;}

      void ∗productor (void ∗p) {

          int num, dato, n;

          n= numero aleatorio();
          for(num= 0; num n; num++) {
            dato= generar dato();
            sem wait (huecos);
            sem wait (pos prod);
            buffer[pos productor]= dato;
            pos productor= (pos productor+ 1) %MAX;
            sem post (pos prod);
            sem post (elementos);
          }

          sem wait (huecos);
          sem wait (pos prod);
          buffer[pos productor]= FIN;
          pos productor= (pos productor+ 1) %MAX;
          sem post (pos prod);
          sem post (elementos);

          pthread exit (NULL);
      }


                                                                    85


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        86   100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗consumidor(void ∗p){

          int pos consumidor= 0, dato, cont fin= 0;
          bool continuar= true;

          while (continuar) {
            sem wait (elementos);
            dato= buffer[pos consumidor];
            sem post (huecos);
            pos consumidor= (pos consumidor+1) %MAX;
            if (dato== FIN) {
              cont fin++;
              if (cont fin== NUMPROD)
                continuar= false;
            } else
              printf (Numero aleatorio: %dn, dato);
          }

          pthread exit (NULL);
      }

      int main (int argc, char ∗argv[]) {

          pthread t hiloconsumidor, hiloproductor[NUMPROD];
          int num;

          sem init (elementos, 0, 0);
          sem init (huecos,    0, MAX);
          sem init (pos prod, 0, 1);




                               @ibaumo
          for (num= 0; num NUMPROD; num++)
            pthread create (hiloproductor[num], NULL, productor, NULL);
          pthread create (hiloconsumidor, NULL, consumidor, NULL);

          for (num= 0; num NUMPROD; num++)
            pthread join (hiloproductor[num], NULL);
          pthread join (hiloconsumidor, NULL);

          sem destroy (huecos);
          sem destroy (elementos);
          sem destroy (pos prod);

          return 0;
      }



52.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          math.h
      #include          stdbool.h

      #define MAX 5
      #define FIN -1

      int buffer[MAX];
      sem t huecos,elementos;
      int inicio, fin;



                                                                    86



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        87   100 Ejercicios resueltos de Sistemas Operativos - UJI
/∗ Devuelve la suma de los d´gitos del n´mero dado ∗/
                            ı           u
int suma digitos (int numero) {

    int suma= 0;

    while (numero 0) {
      suma+= numero %10;
      numero/= 10;
    }

    return suma;
}

/∗ Indica si el n´mero dado es primo ∗/
                 u
bool es primo (int numero) {

    int divisor;

    for (divisor= 2; divisor= sqrt(numero); divisor++)
      if (numero %divisor== 0)
        return false;

    return true;
}

void ∗productor (void ∗param) {

    int pos productor=0;
    int num;




                                 @ibaumo
    for (num= inicio; num fin; num++)
      if (es primo (num)) {
        sem wait (huecos);
        buffer[pos productor]= num;
        pos productor= (pos productor+1) %MAX;
        sem post (elementos);
      }

    sem wait (huecos);
    buffer[pos productor]= FIN;
    sem post (elementos);

    pthread exit(NULL);
}

void ∗consumidor (void ∗param) {

    int pos consumidor=0;
    int dato;
    bool fin= false;

    while (!fin) {
      sem wait (elementos);
      dato= buffer[pos consumidor];
      pos consumidor= (pos consumidor+1) %MAX;
      sem post (huecos);
      if (dato== FIN)
        fin= true;
      else
        printf (N´ mero primo: %d; Suma de los digitos: %dn,
                   u
                 dato, suma digitos(dato));
    }



                                                              87


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   88   100 Ejercicios resueltos de Sistemas Operativos - UJI
pthread exit (NULL);
      }

      int main (int argc, char ∗argv[]) {

          pthread t hiloproductor, hiloconsumidor;

          if (argc!= 3) {
            printf (Indica los dos n´ meros enteros.n);
                                     u
            exit (0);
          }

          inicio= atoi (argv[1]);
          fin=    atoi (argv[2]);

          sem init (huecos, 0, MAX);
          sem init (elementos, 0, 0);

          pthread create (hiloproductor, NULL, productor, NULL);
          pthread create (hiloconsumidor, NULL, consumidor, NULL);

          pthread join (hiloproductor, NULL);
          pthread join (hiloconsumidor, NULL);

          sem destroy (huecos);
          sem destroy (elementos);

          return 0;
      }




                               @ibaumo
53.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          stdbool.h

      #define        MAXALU 25
      #define        MAXRES 4
      #define        RANGO 12
      #define        LIBRE -1
      #define        HORAINICIO 9

      sem t sem tabla, sem consultas;
      int tabla[RANGO], consultas=0;

      void consulta (int id) {

          int num;

          sem wait (sem consultas);
          consultas++;
          if (consultas== 1)
            sem wait(sem tabla);
          sem post (sem consultas);

          for (num= 0; num RANGO; num++)
            if (tabla[num]!= LIBRE)
              printf (Consulta de %d: %d- %d ¡=¿ %dn,
                      id, num+HORAINICIO, num+HORAINICIO+1, tabla[num]);
            else


                                                                    88


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        89   100 Ejercicios resueltos de Sistemas Operativos - UJI
printf (Consulta de %d: %d- %d ¡=¿ LIBREn,
                   id, num+HORAINICIO, num+HORAINICIO+1);

    sem wait (sem consultas);
    consultas--;
    if (consultas== 0)
      sem post (sem tabla);
    sem post (sem consultas);

    pthread exit (NULL);
}

void reserva (int hora, int id) {

    printf (Solicitud de reserva de %d; %d- %dn, id, hora, hora+1);
    sem wait (sem tabla);
    if (tabla[hora-HORAINICIO]!= LIBRE)
      printf (Denegada reserva de %d: %d- %d est´ ocupadan, id, hora, hora+1);
                                                  a
    else {
      tabla[hora-HORAINICIO]= id;
      printf (Reserva de %d: %d- %dn, id, hora, hora+1);
    }
    sem post (sem tabla);
}

void cancela (int id) {

    int num;
    bool hay= false;




                                 @ibaumo
    printf (Solicitud de cancelaci´ n de %dn, id);
                                   o
    sem wait (sem tabla);
    for (num= 0; num RANGO; num++) {
      if (tabla[num]== id) {
        hay= true;
        tabla[num]= LIBRE;
        printf (Cancelaci´ n de %d: %d- %dn, id,
                             o
                   num+HORAINICIO, num+HORAINICIO+1);
      }
    }
    if (hay== false)
      printf (Denegada cancelaci´ n de %d: No tiene reservasn, id);
                                    o
    sem post (sem tabla);
}

void ∗alumno (void ∗dato) {

    int id= ∗(int ∗)dato, num, prob;

    for (num= 0; num MAXRES; num++) {
      prob= random() %100;
      if (prob 50)
        reserva (random() %RANGO+HORAINICIO, id);
      else
        if (prob 75)
           cancela (id);
        else
           consulta (id);
    }
    pthread exit (NULL);
}




                                                              89


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   90    100 Ejercicios resueltos de Sistemas Operativos - UJI
int main (int argc, char ∗argv[]) {

          pthread t hilos[MAXALU];
          int num, dato[MAXALU];

          sem init (sem tabla, 0, 1);
          sem init (sem consultas, 0, 1);

          for (num= 0; num RANGO; num++)
            tabla[num]= LIBRE;

          for (num= 0; num MAXALU; num++) {
            sleep (random() %3); /∗ simula una espera aleatoria ∗/
            dato[num]= num;
            pthread create (hilos[num], NULL, alumno, (void ∗)dato[num]);
          }

          for (num= 0; num MAXALU; num++)
            pthread join (hilos[num], NULL);

          sem destroy (sem tabla);
          sem destroy (sem consultas);

          return 0;
      }



54.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h




                               @ibaumo
      #include          pthread.h
      #include          unistd.h

      #define MAX 100

      int ncochesDirB= 0, ncochesDirA= 0;
      sem t puente, dirB, dirA;

      void ∗direccionB (void ∗dato) {

          int id= (int) dato;

          sleep (random() %20);

          sem wait (dirB);
          ncochesDirB++;
          if (ncochesDirB== 1)
            sem wait (puente);
          printf (Entra en puente Dir B coche %dn, id);
          sem post (dirB);

          sleep (1); /∗ cruzar el puente ∗/

          sem wait (dirB);
          ncochesDirB--;
          printf (Sale del puente Dir B coche %dn, id);
          if (ncochesDirB== 0)
            sem post (puente);
          sem post (dirB);

          pthread exit (NULL);
      }


                                                                    90


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        91   100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗direccionA (void ∗dato) {

         int id= (int) dato;

         sleep (random() %20);

         sem wait (dirA);
         ncochesDirA++;
         if (ncochesDirA== 1)
             sem wait (puente);
         printf (Entra en puente Dir A coche %dn, id);
         sem post (dirA);

         sleep (1); /∗ cruzar el puente ∗/

         sem wait (dirA);
         ncochesDirA--;
         printf (Sale del puente Dir A coche %dn, id);
         if (ncochesDirA== 0)
           sem post (puente);
         sem post (dirA);

         pthread exit (NULL);
     }

     int main (int argc, char ∗argv[]) {

         pthread t hilos[MAX];
         int num;




                               @ibaumo
         sem init (dirA, 0, 1);
         sem init (dirB, 0, 1);
         sem init (puente, 0, 1);

         for (num= 0; num MAX; num+= 2) {
           sleep (random() %3);
           pthread create (hilos[num], NULL,direccionB,(void∗)num);
           pthread create (hilos[num+1],NULL,direccionA,(void∗)(num+1));
         }

         for (num= 0; num MAX; num++)
           pthread join (hilos[num], NULL);

         sem destroy (dirA);
         sem destroy (dirB);
         sem destroy (puente);

         return 0;
     }



55. En primer lugar se calcula lo que ocupa la FAT, que es el tama˜ o del enlace
                                                                       n
    (32 bits) por el n´ mero de entradas de la tabla que, a su vez, es el tama˜ o del
                      u                                                       n
    disco dividido por el tama˜ o del agrupamiento y que en este problema son
                                n
    20GB/(16 ∗ 512bytes) = 20 ∗ 217 entradas. Luego la tabla ocupa 20 ∗ 217 ∗
    32bits = 20 ∗ 219 bytes.
     Si se divide lo que ocupa la tabla por el tama˜ o del agrupamiento se obtiene
                                                   n
     el n´ mero de agrupamientos que ocupa la tabla: 20 ∗ 219 /(16 ∗ 512) = 20 ∗
         u

                                                                    91



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        92   100 Ejercicios resueltos de Sistemas Operativos - UJI
26 = 1280 agrupamientos, que multiplicado por 16, que es el n´ mero de
                                                                     u
     sectores por agrupamiento, se obtiene el n´ mero total de sectores que es
                                               u
     20480.

56. En un sistema de archivos FAT, los bloques se asignan como una lista en-
    lazada que finaliza con la posici´ n fin de lista EOF. Es posible recuperar
                                        o
    datos utilizando los enlaces partiendo desde esa posici´ n EOF hacia atr´ s.
                                                           o                a
    La reconstrucci´ n de la lista de bloques ser´ :
                   o                             a

                                   14 → 15 → 12 → 13 → 10 → 11 → EOF

     La informaci´ n de esa lista de bloques ser´ :
                 o                              a

                      sigan → buscando → yo → no → he → sido → EOF

57. Se trata de un sistema de archivos FAT en el que un fichero de 160KB ocu-
    pa 10 entradas. Como cada sector de disco contiene 512 bytes, el fichero
    ocupa 160 KB / 512 bytes = 320 sectores. Como dicho fichero ocupa 10 en-
    tradas, entonces cada agrupamiento estar´ compuesto por 32 sectores como
                                            a
    m´nimo.
      ı




                               @ibaumo
58. Como el sistema es FAT16 puede direccionar un total de 216 bloques * 1KB
    = 64MB.
     Si la partici´ n es de 2GB, el tama˜ o de bloque deber´a ser como m´nimo
                  o                        n                    ı              ı
     el resultado de dividir el tama˜ o de la partici´ n entre el n´ mero m´ ximo de
                                      n              o             u       a
     bloques, es decir, 2GB/2    16 bloques = 32KB por bloque.


59. El m´ ximo ser´ el n´ mero de entradas de la FAT por el tama˜ o del bloque,
         a           a  u                                       n
    es decir, 2 16 ∗ 4KB = 256M B.

     Si la partici´ n es de 8GB, no es adecuado el tama˜ o de bloque ya que s´ lo
                  o                                    n                     o
     utilizar´a 256MB de esos 8GB.
             ı
     El tama˜ o de bloque adecuado se puede obtener dividiendo el tama˜ o de la
              n                                                             n
     partici´ n entre el n´ mero de ´ndices de la FAT, es decir, 8GB/2
            o             u         ı                                  16 = 128KB

     por bloque.
     Para saber cu´ ntos bloques ocupa la FAT, calculamos el tama˜ o de esta que
                  a                                               n
     es 216 ∗2bytes = 128KB, el cual coincide con el tama˜ o de justo un bloque.
                                                         n

60. En un sistema FAT16 tenemos 216 posibles ´ndices. Por lo tanto, el espa-
                                                   ı
    cio m´ ximo es el n´ mero de ´ndices por el tama˜ o del bloque, es decir,
           a              u           ı                n
    216 ∗ 1KB = 64M B. Como la partici´ n es de 8GB, entonces el espacio
                                              o
    inutilizado es la diferencia, es decir, 8GB − 64M B.
     En el caso del sistema de ficheros basado en nodos-i, el n´ mero de enlaces
                                                              u
     que caben en un bloque se calcula dividiendo el tama˜ o del bloque por el
                                                          n

                                                                    92

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        93   100 Ejercicios resueltos de Sistemas Operativos - UJI
tama˜ o del enlace, es decir, 1KB/16Bytes = 64 enlaces por bloque. Co-
           n
      mo el fichero ocupa 131KB, se utilizar´ n los dos ´ndices directos (con los
                                               a         ı
      que se direcciona un total de 2KB), los dos indirectos simples (con los que
      se direcciona un total de 128KB) y el primer ´ndice indirecto doble (para
                                                     ı
      direccionar el bloque de datos que falta).
      Si el bloque no legible es un bloque de datos s´ lo se perder´a dicho bloque,
                                                       o             ı
      es decir, 1KB. Sin embargo, en el caso de no poder leer un bloque de enlaces,
      si se trata del bloque apuntado por el ´ndice indirecto simple, se perder´an 64
                                             ı                                 ı
      bloques de datos. Si se trata de uno de los dos bloques de ´ndices utilizados
                                                                   ı
      por el ´ndice indirecto doble, se perder´ un s´ lo bloque de datos.
              ı                                a     o

61. Si el fichero tiene 1548 KB, y en cada bloque caben 2KB, utiliza 1548KB /
    2KB = 774 bloques de datos.
      Los cinco ´ndices directos del nodo-i permiten acceder a cinco bloques de
                 ı
      datos, y no se utilizan bloques para almacenar enlaces, por lo que quedan
      por indexar 769 bloques de datos.
      Cada ´ndice indirecto simple permite indexar 256 bloques de datos ya que si
            ı
      el tama˜ o de bloque son 2KB y cada ´ndice ocupa 64 bits, es decir, 8 bytes,
              n                            ı
      tenemos que 2KB / 8bytes = 256 ´ndices. Al mismo tiempo, cada ´ndice
                                         ı                                  ı
      indirecto simple consume un bloque para almacenar enlaces.




                               @ibaumo
      Con los tres enlaces indirectos simples que tiene el nodo-i, indexamos 3*256=
      768 bloques de datos del fichero, consume 3 bloques para almacenar enlaces,
      y a´ n queda un bloque de datos del fichero por indexar.
         u
      Para indexar el bloque de datos que falta, se utilizar´ el primer ´ndice indi-
                                                            a           ı
      recto doble, que utilizar´ 2 bloques para almacenar enlaces (el m´nimo para
                               a                                          ı
      indexar un bloque).
      As´, en total, se utilizan 3 + 2 = 5 bloques para almacenar enlaces.
        ı

62. El n´ mero de ´ndices que caben en un bloque se obtiene dividiendo el tama˜ o
        u         ı                                                           n
    del bloque entre el tama˜ o del ´ndice, es decir, 4KB/32bits= 1024 ´ndices.
                            n       ı                                  ı
      Los ´ndices directos del nodo-i no consumen bloques de ´ndices. Cada ´ndice
          ı                                                   ı             ı
      indirecto simple consume un bloque de ´ndices, y cada ´ndice indirecto doble
                                             ı              ı
      consume 1+1024 bloques de ´ndices. Si el fichero ocupa el m´ ximo tama˜ o
                                    ı                               a          n
      posible, el n´ mero de bloques que contendr´ n ´ndices para ese fichero ser´ :
                   u                             a ı                            a
      2 + 1 + 1024 bloques.
63.   void listado(char nomdir[]) {
        DIR    ∗d;
        struct dirent ∗entrada;
        char   ∗ruta;
        struct stat datos, datos l;

         d= opendir(nomdir);
         if (d== NULL)
           printf(Error al abrir el directorion);


                                                                    93

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        94   100 Ejercicios resueltos de Sistemas Operativos - UJI
else {
            entrada= readdir(d);
            while (entrada!= NULL) {
              ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2);
              sprintf(ruta, %s/ %s, nomdir, entrada-d name);
              stat (ruta,datos);
              lstat(ruta,datos l);
              if(S ISDIR(datos.st mode)  S ISLNK(datos l.st mode))
                 printf( %sn, ruta);
              free(ruta);
              entrada= readdir(d);
            }
            closedir(d);
          }
      }


64.   void listado(char nomdir[]) {
        DIR    ∗d;
        struct dirent ∗entrada;
        char   ∗ruta, ∗ruta zip;
        struct stat datos, datos zip;

          d= opendir(nomdir);
          if (d== NULL)
            printf(Error al abrir el directorion);
          else {
            entrada= readdir(d);
            while (entrada!= NULL) {
              ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2);




                               @ibaumo
              sprintf(ruta, %s/ %s, nomdir, entrada-d name);
              lstat(ruta,datos);
              if(S ISREG(datos.st mode)){
                 ruta zip= malloc(strlen(entrada-d name)+10);
                 sprintf(ruta zip,/tmp/ %s.zip, entrada-d name);
                 if (fork()== 0)
                   execlp(zip, zip, ruta zip, ruta, NULL);
                 else {
                   wait(NULL);
                   stat(ruta zip, datos zip);
                   printf(Datos %ldn, datos.st size - datos zip.st size);
                 }
                 free(ruta zip);
              }
              free(ruta);
              entrada= readdir(d);
            }
            closedir(d);
          }
      }


65.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          unistd.h
      #include          dirent.h
      #include          string.h

      int main (int argc, char ∗argv[]) {

          DIR ∗dir;


                                                                    94


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        95   100 Ejercicios resueltos de Sistemas Operativos - UJI
struct dirent ∗entrada;
          struct stat datos;
          char ∗ ruta;

          if (argc!= 2) {
            printf (Debe especificar un directorion);
            exit (1);
          } else
            printf (El directorio especificado existe y es accesiblen);

          dir= opendir(argv[1]);
          if (dir== NULL) {
            printf (El directorio especificado no existe o no tienes permisos.n);
            exit (1);
          }

          entrada= readdir(dir);
          while (entrada!= NULL) {
            ruta= malloc(strlen (argv[1])+ strlen (entrada-d name)+ 2);
            sprintf (ruta, %s/ %s, argv[1], entrada-d name);
            lstat (ruta, datos);
            if (S ISDIR (datos.st mode))
               if (rmdir (ruta)== 0)
                  printf ( %s se ha borradon, ruta);
               else
                  printf ( %s NO se ha borradon, ruta);
            else
              if (unlink (ruta)== 0)
                 printf ( %s se ha borradon, ruta);
              else




                               @ibaumo
                 printf ( %s NO se ha borradon, ruta);
            free (ruta);
            entrada= readdir(dir);
          }
          closedir(dir);

          return 0;
      }



66.   #include          stdio.h
      #include          stdlib.h
      #include          time.h
      #include          sys/stat.h
      #include          unistd.h

      int main(int argc, char ∗argv[]) {

          struct stat datos;
          int num;

          if (argc 2) {
            printf (Debe especificar al menos un fichero o directorion);
            exit (1);
          }

          for (num= 1; num argc; num++) {
            if (lstat (argv[num], datos)!= 0) {
               printf (Error al ejecutar stat, %s no existen, argv[num]);
            } else {
              if (S ISREG (datos.st mode)) {
                printf ( %s es un ficheron, argv[num]);


                                                                    95


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        96           100 Ejercicios resueltos de Sistemas Operativos - UJI
if (unlink (argv[num])== 0) {
                      printf ( %s se ha borradon, argv[num]);
                      if (datos.st nlink 1)
                        printf (Pero no se han liberado bloquesn);
                      else
                        printf (Se han liberado %d bloquesn, (int)datos.st blocks);
                  } else
                      printf ( %s NO se ha borradon, argv[num]);
                 } else {
                      if (S ISLNK (datos.st mode)) {
                        printf ( %s es un enlace simbolicon, argv[num]);
                        if (unlink (argv[num])== 0)
                           printf ( %s se ha borrado y se han liberado %d bloquesn,
                                   argv[num], (int)datos.st blocks);
                        else
                          printf ( %s NO se ha borradon, argv[num]);
                      } else {
                          if (S ISDIR (datos.st mode)) {
                             printf ( %s es un directorion, argv[num]);
                             if (rmdir (argv[num])== 0)
                               printf ( %s se ha borrado y se han liberado %d bloquesn,
                                          argv[num], (int)datos.st blocks);
                             else
                               printf ( %s NO se ha borradon, argv[num]);
                          }
                      }
                  }
            }
          }
          return 0;




                               @ibaumo
      }



67.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          string.h
      #include          time.h

      void recorre (char ∗nombredir) {

          DIR ∗dir;
          struct dirent ∗entrada;
          struct stat datos;
          char ∗ruta;

          dir= opendir(nombredir);
          if (dir== NULL) {
            printf (Error al abrir el directorio %sn, nombredir);
            return;
          }

          entrada= readdir(dir);
          while (entrada!= NULL) {
            if (strcmp (entrada-d name,.) 
                strcmp (entrada-d name,..)) {
              ruta= malloc (strlen (nombredir)+ strlen (entrada-d name)+ 2);
              sprintf (ruta,  %s/ %s, nombredir, entrada-d name);
              lstat (ruta, datos);
              if (S ISDIR (datos.st mode))


                                                                    96


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        97      100 Ejercicios resueltos de Sistemas Operativos - UJI
recorre (ruta); /∗ recorrido recursivo ∗/
                 else
                   if (S ISREG (datos.st mode)  (datos.st uid== getuid()) 
                       (time(NULL)-datos.st atime 60∗60))
                     printf ( %sn,ruta);
                 free (ruta);
             }
             entrada= readdir(dir);
          }
          closedir (dir);
      }

      int main (int argc, char ∗argv[]) {

          if (argc!= 2)
            printf(Debe especificar un directorion);
          else
            recorre (argv[1]);

          return 0;
      }



68.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          stdbool.h
      #include          sys/types.h




                               @ibaumo
      #include          sys/wait.h
      #include          string.h

      int total= 0, longitud= 0, ∗nodos i= NULL;

      void anyade (int nodo i) {

          if (longitud %10== 0)
            nodos i= (int ∗) realloc (nodos i, (longitud+10)∗ sizeof (int));
          nodos i[longitud]= nodo i;
          longitud++;
      }

      bool esta(int nodo i) {

          int num;

          for (num= 0; num longitud; num++)
            if (nodos i[num]== nodo i)
              return true;

          return false;
      }

      void recorre (char ∗nombredir) {

          DIR ∗dir;
          struct dirent ∗entrada;
          struct stat datos;
          char ∗ruta;

          dir= opendir(nombredir);


                                                                    97


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        98   100 Ejercicios resueltos de Sistemas Operativos - UJI
if (dir== NULL) {
            printf (Error al abrir el directorio %sn, nombredir);
            return;
          }

          entrada= readdir(dir);
          while (entrada!= NULL) {
            if (strcmp(entrada-d name,.)  strcmp(entrada-d name,..)) {
              ruta= malloc(strlen (nombredir)+ strlen(entrada-d name)+ 2);
              sprintf (ruta, %s/ %s, nombredir, entrada-d name);
              lstat (ruta, datos);
              if (S ISDIR (datos.st mode))
                recorre (ruta); /∗ llamada recursiva ∗/
              total+= datos.st size;
              if (datos.st nlink 1) {
                if (esta (datos.st ino)== false)
                 anyade (datos.st ino);
                else
                  total-= datos.st size; /∗ repetido ∗/
              }
              free (ruta);
            }
            entrada= readdir (dir);
          }
          closedir (dir);
      }

      int main(int argc, char ∗argv[]) {

          if (argc!= 2) {




                               @ibaumo
            printf (Debe especificar un directorion);
            exit (1);
          }

          recorre (argv[1]);
          printf (Total en bytes: %dn, total);

          return 0;
      }



69.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          string.h
      #include          time.h

      void recorre (char ∗nombredir, char ∗nombrefile, int nodo i) {

          DIR ∗dir;
          struct dirent ∗entrada;
          struct stat datos;
          char ∗ruta;

          dir= opendir(nombredir);
          if (dir== NULL) {
            printf (Error al abrir el directorio %sn, nombredir);
            return;
          }



                                                                    98


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        99   100 Ejercicios resueltos de Sistemas Operativos - UJI
entrada= readdir(dir);
          while (entrada!= NULL) {
            if (strcmp (entrada-d name,.) 
                strcmp (entrada-d name,..)) {
              ruta= malloc (strlen (nombredir)+ strlen (entrada-d name)+ 2);
              sprintf (ruta,  %s/ %s, nombredir, entrada-d name);
              lstat (ruta, datos);
              if (S ISDIR (datos.st mode))
                recorre (ruta, nombrefile, nodo i); /∗ llamada recursiva ∗/
              else
                if (S ISREG (datos.st mode) 
                     (strcmp (ruta, nombrefile)!= 0) 
                     (datos.st ino== nodo i)) {
                   unlink (ruta);
                   symlink (nombrefile, ruta);
                }
              free (ruta);
            }
            entrada= readdir (dir);
          }
          closedir (dir);
      }

      int main (int argc, char ∗argv[]) {

          struct stat datos;
          if (argc!= 3)
            printf(Debe especificar un fichero y un directorion);
          else {
            lstat (argv[1], datos);




                               @ibaumo
            if (datos.st nlink 1)
              recorre (argv[2], argv[1], datos.st ino);
          }
          return 0;
      }



70.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          string.h
      #include          stdbool.h

      bool tiene extension (char ext[], char nombre[]) {
        return (!strcmp(ext, nombre[strlen(nombre)-strlen(ext)]));
      }

      void crear enlace (char ruta[], char nombre entrada[], char ext[]) {

          char ∗ruta2;
          struct stat datos;

          ruta2= (char ∗) malloc(strlen(/resultado/)+ strlen(ext)+
                                    strlen(nombre entrada)+2);
          sprintf (ruta2, /resultado/ %s/ %s, ext, nombre entrada);
          if (lstat (ruta2, datos)!= 0) /∗ no existe enlace simbolico ∗/
            symlink (ruta, ruta2);
          free (ruta2);
      }



                                                                    99


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7        100   100 Ejercicios resueltos de Sistemas Operativos - UJI
void recorre(char ∗nombredir) {

         DIR ∗dir;
         struct dirent ∗entrada;
         struct stat datos;
         char ∗ruta;

         dir= opendir(nombredir);
         if (dir== NULL) {
           printf (Error al abrir el directorio %sn, nombredir);
           return;
         }

         entrada= readdir(dir);
         while (entrada!= NULL) {
           if (strcmp (entrada-d name,.) 
               strcmp (entrada-d name,..)) {
             ruta= (char∗) malloc (strlen (nombredir)+
                                     strlen (entrada-d name)+ 2);
             sprintf (ruta,  %s/ %s, nombredir, entrada-d name);
             lstat (ruta, datos);
             if (S ISDIR (datos.st mode))
               recorre (ruta);
             else
               if (S ISREG (datos.st mode)) {
                 if (tiene extension (.jpeg, entrada-d name))
                   crear enlace (ruta, entrada-d name, jpeg);
                 else
                   if (tiene extension (.mp3, entrada-d name))
                      crear enlace (ruta, entrada-d name, mp3);




                               @ibaumo
                   else
                     if (tiene extension (.avi, entrada-d name))
                        crear enlace (ruta, entrada-d name, avi);
               }
             free (ruta);
           }
           entrada= readdir (dir);
         }
         closedir (dir);
     }

     int main (int argc, char ∗argv[]) {

         recorre(/media);
         return 0;
     }


71. Si 1GB es el m´ ximo de memoria que se puede direccionar, la direcci´ n
                      a                                                              o
    l´ gica consta de 30 bits. Como el tama˜ o de p´ gina es de 16KB, de los 30
     o                                            n       a
    bits de la direcci´ n l´ gica, 14 bits se utilizan para direccionar el contenido de
                      o o
    la p´ gina, y el resto, 16, para direccionar las p´ ginas, por lo que el n´ mero
         a                                               a                       u
    total de p´ ginas que un proceso puede tener asignadas es de 2
               a                                                         16 .

     Si la tabla de primer nivel contiene 1024 entradas, esto implica que su codifi-
     caci´ n consume 10 bits en la direcci´ n l´ gica, por lo que quedan 6 bits para
          o                                o o
     la tabla de segundo nivel, lo que permite direccionar 26 p´ ginas, es decir,
                                                                    a
     64 p´ ginas. Como el proceso requiere 6401 p´ ginas, se obtiene que necesita
          a                                          a
     101 tablas de segundo nivel.

                                                                    100


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         101   100 Ejercicios resueltos de Sistemas Operativos - UJI
72. Si el tama˜ o de p´ gina son 2KB, esto implica que de los 22 bits de la direc-
                n       a
    ci´ n l´ gica, 11 bits se utilizan para direccionar la p´ gina, por lo que quedan
      o o                                                   a
    11 bits para codificar la tabla de p´ ginas.
                                          a
     Si se utiliza una tabla de p´ ginas de un s´ lo nivel, su tama˜ o es el n´ mero
                                 a              o                  n          u
     de entradas de la tabla por el tama˜ o de la entrada, es decir, 211 ∗ 8 = 214
                                          n
     bytes.
     Si se utiliza una tabla de p´ ginas de dos niveles, 6 bits de la direcci´ n l´ gica
                                  a                                          o o
     se emplean para el primer nivel ya que el enunciado dice que 5 bits son para
     el segundo nivel. Entonces, cada tabla de segundo nivel direcciona hasta 25
     p´ ginas, es decir 32 p´ ginas de 2KB cada una (total 64KB). Como el proceso
       a                    a
     requiere 90KB, hacen falta 2 tablas de segundo nivel. As´, el consumo es
                                                                     ı
     el de una tabla de primer nivel m´ s el de dos de segundo nivel, esto es,
                                           a
     2 6 ∗ 8 + 2 ∗ 25 ∗ 8 = 210 bytes.

     Por lo tanto, el ahorro al utilizar una tabla de p´ ginas de dos niveles es de
                                                       a
     214 − 210 bytes.


73. Como el tama˜ o de la p´ gina es de 4 KB, de los 20 bits de direcci´ n l´ gica,
                  n         a                                           o o
    12 bits son para direccionar el contenido de la p´ gina y, por lo tanto, 8 bits
                                                     a
    son para direccionar las p´ ginas.
                              a
     Si el sistema tiene una tabla de un solo nivel, la tabla tiene 256 entradas, y
     su coste de almacenamiento es de 256 ∗ 16 = 212 bytes.



                               @ibaumo
     Si el sistema tiene una tabla de dos niveles, la tabla de primer nivel tiene 24
     entradas, 16 entradas, al igual que la de segundo nivel. Si un proceso utiliza
     192 KB, se obtiene que necesita 192KB/4KB = 48 p´ ginas, y se emplean
                                                               a
     3 tablas de segundo nivel. Ahora el consumo es de una tabla de primer nivel
     y 3 de segundo, es decir, 24 ∗ 16 + 3 ∗ 24 ∗ 16 = 210 bytes.
     Por lo tanto, el ahorro es 212 − 210 bytes.
74. Si el tama˜ o de p´ gina son 2KB, esto implica que de los 22 bits de la direc-
                n       a
    ci´ n l´ gica, 11 bits se utilizan para direccionar la p´ gina, por lo que quedan
      o o                                                   a
    11 bits para codificar la tabla de p´ ginas. Por lo tanto, el n´ mero m´ ximo de
                                          a                         u        a
    p´ ginas que puede tener asignado un proceso es 211 p´ ginas.
     a                                                         a
     Con una tabla de p´ ginas de dos niveles, la tabla de primer nivel tiene 23
                          a
     entradas, y la de segundo nivel tiene 28 entradas, es decir, 256 entradas. Por
     lo que si un proceso utiliza 1000 p´ ginas, entonces son necesarias 4 tablas
                                         a
     de segundo nivel.
75. En general, utilizar tablas de p´ ginas de dos niveles suele producir un ahorro
                                    a
    en el consumo de memoria comparado con utilizar una tabla de un solo nivel.
    Sin embargo, en el caso de que el proceso requiriera, por ejemplo, la totalidad
    del espacio de memoria, ya no ser´a cierto.
                                         ı
     Por ejemplo, suponer que se disponen de 4 bits para direccionar p´ ginas,
                                                                         a
     donde en un sistema de paginaci´ n de 2 niveles, 2 bits son para el primer
                                    o

                                                                    101

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         102   100 Ejercicios resueltos de Sistemas Operativos - UJI
nivel y 2 bits son para el segundo nivel. En una tabla de un solo nivel hay
     entonces 16 entradas. En una tabla de dos niveles, hay 4 entradas para la
     tabla de primer nivel y, por lo tanto, cuatro tablas de segundo nivel donde
     cada una de estas tablas consta de 4 entradas. Si cada entrada a la tabla de
     p´ ginas requiere n bytes, el coste de almacenar la tabla de p´ ginas de un
      a                                                                a
     nivel es 16 ∗ n bytes, que es menor que el coste de almacenar la tabla de
     p´ ginas de dos niveles que es (4 + 4 ∗ 4) ∗ n bytes. Por lo tanto, en este caso
       a
     la tabla de p´ ginas de dos niveles consume m´ s memoria que la de un nivel.
                  a                                 a
     Respecto al segundo punto, la afirmaci´ n no es correcta. El n´ mero de p´ gi-
                                              o                     u           a
     nas que se pueden asignar a un proceso es independiente de si el sistema
     de paginaci´ n utiliza un nivel o m´ s, ya que en verdad depende del n´ mero
                 o                       a                                   u
     de bits de la direcci´ n l´ gica que se utilizan para direccionar las p´ ginas.
                           o o                                              a
     Siguiendo con el ejemplo anterior, ese n´ mero de bits es 4, y el n´ mero
                                                  u                          u
     m´ ximo de p´ ginas es por lo tanto de 16.
       a           a

76. Si se direcciona 1GB (230 bytes), entonces la direcci´ n l´ gica es de 30 bits.
                                                              o o
    Si la p´ gina es de 32KB (2
           a                       15 bytes), y cada palabra son 2 bytes, har´ n falta
                                                                               a
    14 bits para direccionar el contenido de una p´ gina. En consecuencia, quedan
                                                     a
    16 bits de la direcci´ n l´ gica para la tabla de p´ ginas. Si el proceso requiere
                         o o                            a
                                                                         ´
    90MB, necesita 90MB/32KB = 2880 p´ ginas. Si se utiliza una unica tabla de
                                               a
    p´ ginas, el consumo de memoria ser´ el tama˜ o de la tabla por el tama˜ o de
      a                                     a         n                          n




                               @ibaumo
    la entrada, es decir, 2 16 ∗ 16 = 220 bytes. Si se utiliza una tabla de p´ ginas
                                                                                a
    de dos niveles, donde 8 bits son para el primer nivel y otros 8 bits para el
    segundo, el proceso utilizar´ la tabla de primer nivel m´ s 12 de segundo, ya
                                   a                             a
    que cada tabla de segundo nivel apunta a 256 p´ ginas y el proceso requiere
                                                          a
    un total de 2880. El consumo en este caso es de 28 ∗ 16 + 12 ∗ 28 ∗ 16 =
    13 ∗ 212 bytes, y el ahorro es la diferencia de los costes obtenidos, es decir,
    220 − 13 ∗ 212 bytes.

77. El sistema requiere 12 bits para direccionar el contenido de una p´ gina ya
                                                                          a
    que la p´ gina es de 32KB (2
             a                   15 bytes) y el tama˜ o de la palabra es de 64 bits
                                                      n
    (2 3 bytes). Quedan 18 bits para la tabla de p´ ginas.
                                                  a
     Si el proceso requiere 256MB, entonces 256M B/32KB = 213 es el n´ mero     u
     de p´ ginas. En el caso de la tabla de p´ ginas de dos niveles, se utilizan 9 bits
          a                                  a
     para el primer nivel y otros tantos para el segundo. Por lo que el proceso
     requiere 213 /29 = 24 tablas de segundo nivel. As´, el ahorro de memoria
                                                            ı
     ser´ la diferencia entre los consumos de ambas representaciones, es decir,
        a
     218 ∗ 8 − (29 + 24 ∗ 29 ) ∗ 8 bytes.

78. Con 3 marcos:

               FIFO: 10 fallos de p´ gina
                                   a
                   • P´ gina 0: 2 → 4 → 3 → 6
                      a
                   • P´ gina 1: 3 → 5 → 1
                      a

                                                                    102

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         103   100 Ejercicios resueltos de Sistemas Operativos - UJI
• P´ gina 2: 1 → 2 → 5
                      a
               LRU: 9 fallos de p´ gina
                                 a
                   • P´ gina 0: 2 → 5
                      a
                   • P´ gina 1: 3 → 4 → 3 → 6
                      a
                   • P´ gina 2: 1 → 5 → 1
                      a

      Con 4 marcos:

               FIFO: 9 fallos de p´ gina
                                  a
                   •    P´ gina 0: 2 → 5 → 6
                         a
                   •    P´ gina 1: 3 → 2
                         a
                   •    P´ gina 2: 1 → 3
                         a
                   •    P´ gina 3: 4 → 1
                         a
               LRU: 8 fallos de p´ gina
                                 a
                   •    P´ gina 0: 2 → 6
                         a
                   •    P´ gina 1: 3 → 5
                         a
                   •    P´ gina 2: 1 → 3
                         a
                   •    P´ gina 3: 4 → 1
                         a

      Para ambas pol´ticas se reduce el n´ mero de fallos de p´ gina al aumentar el
                    ı                    u                    a



                               @ibaumo
      n´ mero de marcos a 4.
       u

79.            FIFO: 8 fallos de p´ gina
                                  a
                   •    P´ gina 0: 4 → 3
                         a
                   •    P´ gina 1: 2 → 5
                         a
                   •    P´ gina 2: 1 → 4
                         a
                   •    P´ gina 3: 6 → 1
                         a
               LRU: 11 fallos de p´ gina
                                  a
                   •    P´ gina 0: 4 → 2 → 1
                         a
                   •    P´ gina 1: 2 → 3 → 4
                         a
                   •    P´ gina 2: 1 → 5 → 3
                         a
                   •    P´ gina 3: 6 → 5
                         a
               ´
               Optima: 7 fallos de p´ gina
                                    a
                    •   P´ gina 0: 4 → 1
                         a
                    •   P´ gina 1: 2 → 5
                         a
                    •   P´ gina 2: 1 → 3
                         a
                    •   P´ gina 3: 6
                         a

80.            FIFO: 7 fallos de p´ gina
                                  a
                   • P´ gina 0: 1 → 5 → 1
                      a

                                                                    103

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         104   100 Ejercicios resueltos de Sistemas Operativos - UJI
• P´ gina 1: 2 → 6
                      a
                   • P´ gina 2: 3 → 2
                      a
               LRU: 8 fallos de p´ gina
                                 a
                   • P´ gina 0: 1 → 3
                      a
                   • P´ gina 1: 2 → 6 → 1
                      a
                   • P´ gina 2: 3 → 5 → 2
                      a
               ´
               Optima: 6 fallos de p´ gina
                                    a
                   • P´ gina 0: 1 → 5 → 6 → 1
                      a
                   • P´ gina 1: 2
                      a
                   • P´ gina 2: 3
                      a

81.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          string.h
      #include          time.h

      int tubo1[2], tubo2[2], tubo3[2], tubo4[2];




                               @ibaumo
      void cierraTuberias (void) {
        close (tubo1[0]); close (tubo1[1]);
        close (tubo2[0]); close (tubo2[1]);
        close (tubo3[0]); close (tubo3[1]);
        close (tubo4[0]); close (tubo4[1]);
      }

      void recorre (char ∗nombredir) {

         DIR ∗dir;
         struct dirent ∗entrada;
         struct stat datos;
         char ∗ruta;

         dir= opendir(nombredir);
         if (dir==NULL) {
           printf(Error al abrir el directorio %sn, nombredir);
           return;
         }

         entrada= readdir(dir);
         while (entrada!=NULL) {
           if (strcmp(entrada-d name,.)  strcmp(entrada-d name,..)) {
             ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2);
             sprintf (ruta, %s/ %s,nombredir,entrada-d name);
             lstat (ruta,datos);
             if (S ISDIR(datos.st mode)) {
               recorre (ruta); /∗ llamada recursiva ∗/
               if (rmdir(ruta)== 0) { /∗ directorio borrado ∗/
                 write (tubo1[1], entrada-d name, strlen(entrada-d name));
                 write (tubo1[1], n, 1);
               }


                                                                    104

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         105   100 Ejercicios resueltos de Sistemas Operativos - UJI
} else
             if (S ISREG (datos.st mode)  (datos.st uid== getuid())) {
                 if (time(NULL)- datos.st atime  2∗7∗24∗60∗60) {
                   if (unlink (ruta)== 0) { /∗ fichero borrado ∗/
                     write (tubo1[1], entrada-d name,
                            strlen(entrada-d name));
                     write (tubo1[1], n, 1);
                   }
                 } else /∗ el aviso ∗/
                 if (time(NULL)- datos.st atime  1∗7∗24∗60∗60) {
                   write (tubo2[1], entrada-d name,
                          strlen(entrada-d name));
                   write (tubo2[1], n, 1);
               }
             }
           free (ruta);
       }
       entrada= readdir(dir);
    }
    closedir (dir);
}

int main(int argc, char ∗argv[]) {

    int numproc;

    if (argc!= 2) {
      printf(Debes especificar una direccion de correo electronico.n);
      exit(1);
    }




                                 @ibaumo
    pipe     (tubo1);
    pipe     (tubo2);
    pipe     (tubo3);
    pipe     (tubo4);

    for (numproc= 0; numproc 4; numproc++)
      if (fork()== 0) break;

    switch (numproc) {
      case 0:
        dup2 (tubo1[0], STDIN FILENO);
        dup2 (tubo3[1], STDOUT FILENO);
        cierraTuberias ();
        execlp (sort, sort, NULL);
        break;
      case 1:
        dup2(tubo2 [0], STDIN FILENO);
        dup2(tubo4 [1], STDOUT FILENO);
        cierraTuberias ();
        execlp (sort, sort, NULL);
        break;
      case 2:
        dup2 (tubo3[0], STDIN FILENO);
        cierraTuberias ();
        execlp (mail, mail, argv[1], -s,
                Ficheros y directorios borrados, NULL);
        break;
      case 3:
        dup2 (tubo4[0], STDIN FILENO);
        cierraTuberias ();
        execlp (mail, mail, argv[1], -s,



                                                            105


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   106   100 Ejercicios resueltos de Sistemas Operativos - UJI
Ficheros que se borraran en breve, NULL);
                break;
              case 4:
                recorre (/tmp);
                cierraTuberias ();
                wait (NULL);
                wait (NULL);
                wait (NULL);
                wait (NULL);
          }

          return 0;
      }



82.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          string.h
      #include          sys/types.h
      #include          sys/wait.h

      #define MAXLON 2000

      int tubo[2];

      void recorre(char ∗nombredir) {




                               @ibaumo
          DIR ∗dir;
          struct dirent ∗entrada;
          struct stat datos;
          char ∗ruta;
          int pos;

          dir= opendir(nombredir);
          if (dir== NULL) {
            printf (Error al abrir el directorio %sn, nombredir);
            return;
          }

          entrada= readdir(dir);
          while (entrada!= NULL) {
            if (strcmp (entrada-d name,.) 
                strcmp (entrada-d name,..)) {
              ruta= (char∗) malloc (strlen (nombredir)+
                                      strlen (entrada-d name)+ 2);
              sprintf (ruta,  %s/ %s, nombredir, entrada-d name);
              lstat (ruta, datos);
              if (S ISDIR (datos.st mode))
                recorre (ruta);
              else
                if (S ISREG (datos.st mode)) {
                  pos= strlen(entrada-d name)-2;
                   if (strcmp (entrada-d name[pos],.c)== 0 ||
                       strcmp (entrada-d name[pos],.h)== 0) {
                     write (tubo[1], ruta, strlen(ruta));
                     write (tubo[1], n, 1);
                   }
                }
              free (ruta);


                                                                    106


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         107   100 Ejercicios resueltos de Sistemas Operativos - UJI
}
             entrada= readdir (dir);
          }
          closedir (dir);
      }

      int main(int argc, char ∗argv[]) {

          char linea[MAXLON], ∗nombre;
          struct stat datos1, datos2;
          int pos;

          if (argc!= 3) {
            printf (Debe especificar dos directoriosn);
            exit (1);
          }

          pipe (tubo);

          if (fork()== 0) {
            close    (tubo[0]);
            recorre (argv[1]);
            close    (tubo[1]);
          } else {
            dup2 (tubo[0], STDIN FILENO);
            close (tubo[0]);
            close (tubo[1]);
            while (gets(linea)!= NULL) {
              pos= strlen(linea)-1;
              while (linea[pos]!= ’/’)




                               @ibaumo
                pos--;
              nombre= (char∗) malloc (strlen (argv[2])+
                                        strlen(linea[pos+1])+ 2);
              sprintf (nombre,  %s/ %s, argv[2], linea[pos+1]);
              lstat (linea, datos2);
              if ((lstat (nombre, datos1)!= 0) ||
                   (datos1.st mtime datos2.st mtime)) {
                if (fork()== 0)
                   execlp (cp, cp, linea, nombre, NULL);
                else
                   wait (NULL);
              }
              free (nombre);
            }
            wait (NULL);
          }
          return 0;
      }



83.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          sys/wait.h
      #include          dirent.h
      #include          unistd.h
      #include          time.h
      #include          string.h

      int n fich= 0;
      int ahorro= 0;



                                                                    107


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         108   100 Ejercicios resueltos de Sistemas Operativos - UJI
void recorre (char ∗nombredir) {

    DIR ∗d;
    struct dirent ∗entrada;
    struct stat datosPs, datosPdf;
    char ∗ruta, ∗rutapdf;

    d= opendir(nombredir);
    if (d== NULL) {
      printf(Error al abrir el directorion);
      return;
    }

    entrada= readdir(d);
    while (entrada!=NULL) {
      if (strcmp(entrada-d name,.) 
          strcmp(entrada-d name,..)) {
        ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2);
        sprintf(ruta, %s/ %s,nombredir,entrada-d name);
        lstat (ruta,datosPs);
        if (S ISDIR(datosPs.st mode))
          recorre(ruta);
        else
          if (S ISREG(datosPs.st mode)) {
            if (strcmp(ruta[strlen(ruta)-3], .ps)== 0) {/ ∗ .ps? ∗/
              rutapdf= malloc(strlen(ruta)+1);
              sprintf(rutapdf, %s,ruta);
              rutapdf[strlen(ruta)-3]=’0’;
              strcat (rutapdf, .pdf);
              if (fork()== 0)




                                 @ibaumo
                execlp (ps2pdf, ps2pdf, ruta, rutapdf, NULL);
              wait(NULL);
              n fich++;
              lstat(rutapdf,datosPdf);
              ahorro+= (datosPs.st blocks - datosPdf.st blocks);
              unlink(ruta);
              free(rutapdf);
            }
          }
        free(ruta);
      }
      entrada= readdir(d);
    }
    closedir(d);
}

int main(int argc, char ∗argv[]) {

    int i;
    time t inicio;

    if (argc== 1) {
      printf(Debe especificar al menos un directorion);
      exit(1);
    }

    for (i= 1; i argc; i++) {
      if (fork()== 0) {
        inicio= time(NULL);
        recorre (argv[i]);
        printf (Numero de ficheros transformados: %dn, n fich);
        printf (Ahorro de espacio en bloques: %dn, ahorro);



                                                            108


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   109   100 Ejercicios resueltos de Sistemas Operativos - UJI
printf (Tiempo en procesar el directorio %s: %ldn, argv[i],
                           (time(NULL)- inicio));
                  exit(0);
              }
          }

          for (i= 1; i argc; i++)
            wait(NULL);

          return 0;
      }



84.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          time.h

      #define MAX 20

      struct param {
         int num estudiante;
         int num grupo;
      };

      struct param buffer[MAX];

      sem t huecos,elementos,mutex;




                               @ibaumo
      int     pos productor= 0;
      int     num estudiantes, cantidad grupos, plazas por grupo;
      int     ∗grupo de alumno;
      int     ∗plazas libres;

      void init datos() {

          int i;

          grupo de alumno= (int∗)malloc(sizeof(int)∗num estudiantes);
          for (i= 0; i num estudiantes; i++)
            grupo de alumno[i]= -1;
          plazas libres= (int∗)malloc(sizeof(int)∗cantidad grupos);
          for (i= 0; i cantidad grupos; i++)
            plazas libres[i]= plazas por grupo;
      }

      int ∗decide preferencias (void) {

          int ∗peticiones;
          int i,pos1,pos2,aux;

          peticiones= (int ∗) malloc(sizeof(int)∗cantidad grupos);
          for (i= 0; i cantidad grupos; i++)
            peticiones[i]= i;
          for (i= 0; i cantidad grupos; i++) {
            pos1= random() %cantidad grupos;
            pos2= random() %cantidad grupos;
            aux= peticiones[pos1];
            peticiones[pos1]= peticiones[pos2];
            peticiones[pos2]= aux;


                                                                    109


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         110      100 Ejercicios resueltos de Sistemas Operativos - UJI
}
    return peticiones;
}

int grupo asignado (int num estudiante) {
  return (grupo de alumno[num estudiante]);
}

int hay plazas libres (int num grupo) {
  return (plazas libres[num grupo]0);
}

void asignar grupo (int estudiante, int grupo) {

    if (grupo de alumno[estudiante]==-1) {
      grupo de alumno[estudiante]= grupo;
      plazas libres[grupo]--;
    }
    else {
      printf(Error inesperadon);
      pthread exit(NULL);
    }
}

void ∗productor(void ∗p) {

    int num estudiante= ∗(int ∗)p;
    int i;
    int ∗peticiones;
    struct param dato;




                                 @ibaumo
  peticiones= decide preferencias ();
  for (i= 0; i cantidad grupos; i++) {
    dato.num estudiante= num estudiante;
    dato.num grupo= peticiones[i];
    printf (El estudiante %d pide el grupo %dn, num estudiante,
peticiones[i]);
    sem wait(huecos);
    sem wait(mutex);
    buffer[pos productor]= dato;
    pos productor= (pos productor+1) %MAX;
    sem post(mutex);
    sem post(elementos);
    if (grupo asignado(num estudiante)!=-1)
      pthread exit(NULL);
  }
  pthread exit(NULL);
}

void ∗consumidor (void ∗p) {

    int pos consumidor= 0;
    int asignados= 0;
    struct param dato;

    while (asignados num estudiantes) {
      sem wait(elementos);
      dato= buffer[pos consumidor];
      pos consumidor= (pos consumidor+1) %MAX;
      sem post(huecos);

       if (hay plazas libres(dato.num grupo)) {



                                                            110


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   111   100 Ejercicios resueltos de Sistemas Operativos - UJI
if (grupo asignado(dato.num estudiante)!=-1)
                printf(--¿ Peticion rechazada. Estudiante %d, grupo %d. El estudiante ya tiene grupo
      asignadon,
                       dato.num estudiante,dato.num grupo);
              else {
                asignar grupo(dato.num estudiante, dato.num grupo);
                printf(---¿ Al estudiante %d se le asigna el
      grupo %dn,dato.num estudiante, dato.num grupo);
                asignados++;
              }
            } else
                printf(--¿ Peticion rechazada. Estudiante %d, grupo %d. Grupo llenon,
                       dato.num estudiante,dato.num grupo);

          }
          pthread exit(NULL);
      }


      int main (int argc, char ∗argv[]) {

          pthread t ∗estudiantes, gestor;
          int i, ∗datos;

        if (argc!= 4) {
          printf(Error. Debe proporcionar tres parametros: Num. estudiantes, Num. de grupos y
      Tama˜ o de grupon);
          n
          exit(1);
        }




                               @ibaumo
          num estudiantes= atoi(argv[1]);
          cantidad grupos= atoi(argv[2]);
          plazas por grupo= atoi(argv[3]);

          if (num estudiantes cantidad grupos∗plazas por grupo) {
            printf(Error. No hay plazas para todos los estudiantesn);
            exit(1);
          }

        init datos();
        datos= (int∗) malloc(sizeof(int)∗num estudiantes);
        estudiantes= (pthread t∗)
      malloc(sizeof(pthread t)∗num estudiantes);

          sem init(huecos,    0, MAX);
          sem init(elementos, 0, 0);
          sem init(mutex,     0, 1);

          pthread create (gestor, NULL, consumidor, NULL);
          for (i= 0; i num estudiantes; i++) {
            datos[i]= i;
            pthread create (estudiantes[i], NULL, productor, datos[i]);
          }

          pthread join(gestor, NULL);

          return 0;
      }



85.   #include stdio.h
      #include stdlib.h


                                                                    111


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         112           100 Ejercicios resueltos de Sistemas Operativos - UJI
#include         sys/stat.h
#include         dirent.h
#include         unistd.h
#include         string.h
#include         time.h
#include         sys/types.h
#include         sys/wait.h

void recorre(char ∗nombredir) {

    DIR ∗d;
    struct dirent ∗entrada;
    struct stat datos;
    char ∗ruta;

    d= opendir(nombredir);
    if(d==NULL){
      printf(Error al abrir el directorio %sn,nombredir);
      return;
    }

    entrada= readdir(d);
    while (entrada!= NULL) {
      if(strcmp(entrada-d name,.) 
         strcmp(entrada-d name,..)) {
         ruta=malloc(strlen(nombredir)+strlen(entrada-d name)+2);
         sprintf(ruta, %s/ %s,nombredir,entrada-d name);
         lstat(ruta,datos);
         if (S ISDIR(datos.st mode))
           recorre(ruta);




                                 @ibaumo
         else
           if(fork()== 0)
              if (datos.st size2∗1024∗1024)
                execlp(lpr,lpr,-P,ps1,ruta,NULL);
              else
                execlp(lpr,lpr,-P,ps2,ruta,NULL);
           else
              wait(NULL);
         free(ruta);
       }
      entrada= readdir(d);
    }
    closedir(d);
}

int main(int argc,char ∗argv[]) {

    int num;
    time t inicio,fin;

    inicio= time(NULL);

    for (num= 1; num argc; num++)
      if (fork()== 0) {
        recorre(argv[num]);
        exit(0);
      }

    for (num= 1; num argc; num++)
      wait(NULL);

    fin=time(NULL);



                                                            112


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   113   100 Ejercicios resueltos de Sistemas Operativos - UJI
printf(Duracion: %ld segundosn,fin-inicio);

          return 0;
      }



86.   #include          stdlib.h
      #include          stdio.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          time.h

      #define N 30

      typedef struct {
        int id;
        int tiempo;
      } param;

      sem t svar, slect, stam;
      int ngallo= 0;


      void comer(){}
      void beber(){}
      void dormir (int id, int tiempo){
        sleep(tiempo);
        printf(El gallo %d ha dormido %d horasn,id,tiempo);
      }




                               @ibaumo
      void ∗galloSalvaje (void ∗datos) {

          param ∗mi dato= (param ∗)datos;
          int iden= mi dato-id;
          int temp= mi dato-tiempo;

          while(1){
            comer();

             sem wait(svar);
             printf(El gallo salvaje %d esta bebiendon,iden);
             beber();
             printf(El gallo salvaje %d ha terminado de bebern,iden);
             sem post(svar);

            dormir(iden,temp);
          }
          pthread exit(NULL);
      }

      void ∗galloDomestico (void ∗ datos) {

          param ∗mi dato= (param ∗)datos;
          int iden= mi dato-id;
          int temp= mi dato-tiempo;

          while(1){
            comer();

             sem wait(slect);
             ngallo++;


                                                                    113


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         114   100 Ejercicios resueltos de Sistemas Operativos - UJI
if(ngallo==1) sem wait(svar);
             sem post(slect);

             sem wait(stam);
             printf(El gallo domestico %d esta bebiendon,iden);
             beber();
             printf(El gallo domestico %d ha terminado de bebern,iden);
             sem post(stam);

             sem wait(slect);
             ngallo--;
             if(ngallo==0) sem post(svar);
             sem post(slect);

            dormir(iden,temp);
          }
          pthread exit(NULL);
      }

      int main (int argc,char ∗argv[]){

          pthread t th[N];
          int i;
          param vector[N];

          sem init(svar,0,1);
          sem init(slect,0,1);
          sem init(stam,0,6);

          for(i=0;i25;i++){ /∗ crea los gallos domesticos ∗/




                               @ibaumo
            vector[i].tiempo=7+random() %4;
            vector[i].id=i;
            pthread create(th[i],NULL,galloDomestico,(void ∗) vector[i]);
          }
          for(i=25;iN;i++){ /∗ crea los gallos salvajes ∗/
            vector[i].tiempo=7+random() %4;
            vector[i].id=i;
            pthread create(th[i],NULL,galloSalvaje,(void ∗) vector[i]);
          }

          for(i=0;iN;i++)
            pthread join(th[i],NULL);

          sem destroy(svar);
          sem destroy(slect);
          sem destroy(stam);

          exit(0);
      }



87.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          math.h
      #include          stdbool.h

      #define MAX 5

      int buffer[MAX];


                                                                    114


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         115   100 Ejercicios resueltos de Sistemas Operativos - UJI
sem t huecos, elementos, pos prod, prod;
int pos productor=0, cont prod= 0, cont primos= 0;

int suma digitos es impar (int numero) {

    int suma= 0;
    while (numero0) {
      suma+= numero %10;
      numero/= 10;
    }
    return (suma %2==1);
}

int es primo(int numero) {

    int divisor;
    for (divisor=2; divisor= sqrt(numero); divisor++)
      if (numero %divisor==0)
        return 0;
    return 1;
}

void ∗productor(void ∗p) {

    int i, dato;

    for (i= 0;i 1000; i++) {
      dato= random() %1000;
      sem wait(prod);
      cont prod++;




                                 @ibaumo
      sem post(prod);
      if (es primo(dato)) {
        sem wait(huecos);
        sem wait(pos prod);
        buffer[pos productor]= dato;
        pos productor= (pos productor+1) %MAX;
        sem post(pos prod);
        sem post(elementos);
      }
    }

    sem wait(huecos);
    sem wait(pos prod);
    buffer[pos productor]= -1;
    pos productor= (pos productor+1) %MAX;
    sem post(pos prod);
    sem post(elementos);

    pthread exit(NULL);
}

void ∗consumidor(void ∗p) {

    int pos consumidor=0;
    int dato, cont= 0, term= 0;
    bool fin= false;

    while (!fin) {
      sem wait(elementos);
      dato= buffer[pos consumidor];
      pos consumidor= (pos consumidor+1) %MAX;
      sem post(huecos);



                                                            115


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   116   100 Ejercicios resueltos de Sistemas Operativos - UJI
if (dato== -1) {
               term++;
               if (term== 3)
                 fin= true;
             } else {
               cont primos++;
               if (suma digitos es impar(dato)) {
                 printf( %d ,dato);
                 fflush(stdout);
                 cont++;
                 if (cont== 50)
                   fin= true;
               }
             }
          }
          pthread exit(NULL);
      }


      int main(int argc, char ∗argv[]) {

          pthread t th[4];
          int i;

          sem    init(huecos, 0, MAX);
          sem    init(elementos, 0, 0);
          sem    init(pos prod, 0, 1);
          sem    init(prod, 0, 1);

          for (i= 0; i 3; i++)




                               @ibaumo
            pthread create (th[i], NULL, productor, NULL);
          pthread create (th[3], NULL, consumidor, NULL);

          pthread join(th[3], NULL);

          printf (n);
          printf (Numeros primos procesados: %dn, cont primos);
          printf (Numeros alatorios generados: %dn, cont prod);

          sem    destroy(huecos);
          sem    destroy(elementos);
          sem    destroy(pos prod);
          sem    destroy(prod);

          return 0;
      }



88.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          string.h
      #include          time.h

      int tubo1[2], tubo2[2];

      void cierraTuberias (void) {
        close (tubo1[0]); close (tubo1[1]);


                                                                    116


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         117   100 Ejercicios resueltos de Sistemas Operativos - UJI
close (tubo2[0]);                     close (tubo2[1]);
}

void recorre (char ∗nombredir) {

    DIR ∗d;
    struct dirent ∗entrada;
    struct stat datos;
    char ∗ruta;

    d= opendir(nombredir);
    if (d==NULL) {
      printf(Error al abrir el directorio %sn, nombredir);
      return;
    }

    entrada= readdir(d);
    while (entrada!=NULL) {
      if (strcmp(entrada-d name,.) 
          strcmp(entrada-d name,..)) {
        ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2);
        sprintf (ruta, %s/ %s,nombredir,entrada-d name);
        lstat (ruta,datos);
        if (S ISDIR(datos.st mode)) {
          recorre (ruta);
          if (rmdir(ruta)== 0) {
            write(tubo1[1], entrada-d name,
                              strlen(entrada-d name));
            write(tubo1[1], n, 1);
          }




                                 @ibaumo
        } else
          if (S ISREG (datos.st mode) 
              (datos.st uid == getuid())) {
            if (datos.st size 2∗1024∗1024) {
               if (unlink(ruta)== 0) {
                 write(tubo1[1], entrada-d name,
                                  strlen(entrada-d name));
                 write(tubo1[1], n, 1);
               }
            } else
            if (datos.st size  1∗1024∗1024) {
               write(tubo2[1], entrada-d name,
                                strlen(entrada-d name));
               write(tubo2[1], n, 1);
            }
          }
        free(ruta);
      }
      entrada= readdir(d);
    }
    closedir(d);
}

int main(int argc, char ∗argv[]) {

    int i;

    if (argc!=2) {
      printf(Debe especificar una direccion de correo electronicon);
      exit(1);
    }




                                                            117


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   118   100 Ejercicios resueltos de Sistemas Operativos - UJI
pipe (tubo1);
         pipe (tubo2);

         for (i= 0; i 2; i++)
           if (fork()== 0) break;

         switch (i) {
           case 0:
             dup2(tubo1[0], STDIN FILENO);
             cierraTuberias();
             execlp (mail, mail, argv[1], -s,
                      Ficheros y directorios borrados de tmp, NULL);
             break;
           case 1:
             dup2(tubo2[0], STDIN FILENO);
             cierraTuberias();
             execlp (mail, mail, argv[1], -s,
                      Ficheros que ocupan mucho espacio en tmp, NULL);
             break;
           case 2:
             recorre(/tmp);
             cierraTuberias();
             wait (NULL);
             wait (NULL);
             break;
         }

         return 0;
     }




                               @ibaumo
89. Soluci´ n al apartado a):
          o
     #include           stdio.h
     #include           stdlib.h
     #include           semaphore.h
     #include           pthread.h
     #include           unistd.h

     #define N vehiculos 200
     sem t estacion;

     void ∗camion (void ∗ nada) {

         long int n= (long int) pthread self();

         printf (Llega camion: %ldn, n);
         sem wait(estacion);
         sem post(estacion);
         printf (Se atiende camion: %ldn, n);
         sleep(random() %3+2); /∗ tiempo invertido en atender al camion ∗/
         printf (Sale camion: %ldn, n);
         pthread exit(NULL);
     }

     void ∗barco (void ∗ nada) {

         long int n= (long int) pthread self();

         printf (Llega barco: %ldn, n);
         sem wait(estacion);
         printf(Se atiende barco: %ldn, n);
         sleep(random() %5+5); /∗ tiempo invertido en atender al barco ∗/


                                                                    118


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         119   100 Ejercicios resueltos de Sistemas Operativos - UJI
printf (Sale barco: %ldn, n);
    sem post(estacion);
    pthread exit(NULL);
}

int main(int argc, char ∗argv[]) {

    int i;
    pthread t th[N vehiculos];

    sem init(estacion, 0, 1);
    for (i= 0; i N vehiculos; i++) {
      sleep(random() %3);
      if (random() %100  95)
        pthread create(th[i], NULL, camion, NULL);
      else
        pthread create(th[i], NULL, barco, NULL);
    }

    for (i= 0; i N vehiculos; i++)
      pthread join(th[i], NULL);

    sem destroy(estacion);
    return 0;
}

Soluci´ n al apartado b):
      o
#include         stdio.h
#include         stdlib.h




                                 @ibaumo
#include         semaphore.h
#include         pthread.h
#include         unistd.h

#define N vehiculos 200
sem t estacion, camiones;
int ncamiones= 0;

void ∗camion (void ∗ nada) {

    long int n= (long int) pthread self();

    printf (Llega camion: %ldn, n);
    sem wait(camiones);
    ncamiones++;
    if (ncamiones== 1)
      sem wait(estacion);
    sem post(camiones);
    printf (Se atiende camion: %ldn, n);
    sleep(random() %3+2); /∗ tiempo invertido en atender al camion ∗/
    printf (Sale camion: %ldn, n);
    sem wait(camiones);
    ncamiones--;
    if (ncamiones== 0)
      sem post(estacion);
    sem post(camiones);

    pthread exit(NULL);
}




                                                             119


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   120   100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗barco (void ∗ nada) {

          long int n= (long int) pthread self();

          printf (Llega barco: %ldn, n);
          sem wait(estacion);
          printf(Se atiende barco: %ldn, n);
          sleep(random() %5+5); /∗ tiempo invertido en atender al barco ∗/
          printf (Sale barco: %ldn, n);
          sem post(estacion);
          pthread exit(NULL);
      }

      int main(int argc, char ∗argv[]) {

          int i;
          pthread t th[N vehiculos];

          sem init(estacion, 0, 1);
          sem init(camiones, 0, 1);
          for (i= 0; i N vehiculos; i++) {
            sleep(random() %3);
            if (random() %100  95)
              pthread create(th[i], NULL, camion, NULL);
            else
              pthread create(th[i], NULL, barco, NULL);
          }

          for (i= 0; i N vehiculos; i++)
            pthread join(th[i], NULL);




                               @ibaumo
          sem destroy(estacion);
          sem destroy(camiones);
          return 0;
      }



90.   #include          stdio.h
      #include          sys/types.h
      #include          wait.h
      #include          unistd.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          fcntl.h
      #include          time.h

      int main (int argc, char ∗argv[]) {

          int tub1[2],tub2[2];
          int fich;
          time t ini, fin;

          if (fork()!= 0) {
             ini=time(NULL);
             wait(NULL);
             fin= time(NULL);
             printf (Tiempo total: %ld segundosn, fin-ini);
             return 0;
          }
          pipe (tub1);
          if (fork()!= 0){
            dup2 (tub1[0], STDIN FILENO);


                                                                    120


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         121   100 Ejercicios resueltos de Sistemas Operativos - UJI
close (tub1[0]);
           close (tub1[1]);
           fich= creat (argv[3], 00644);
           dup2 (fich, STDOUT FILENO);
           close(fich);
           execlp (uniq, uniq, NULL);
         } else {
           pipe (tub2);
           if (fork()!= 0){
             dup2 (tub1[1],STDOUT FILENO);
             dup2 (tub2[0],STDIN FILENO);
             close (tub1[1]);
             close (tub1[0]);
             close (tub2[1]);
             close (tub2[0]);
             execlp (sort, sort, -r, NULL);
           } else {
             dup2 (tub2[1], STDOUT FILENO);
             close (tub1[0]);
             close (tub1[1]);
             close (tub2[0]);
             close (tub2[1]);
             execlp (grep, grep, argv[1], argv[2], NULL);
           }
         }
     }


91. Soluci´ n al apartado a):
          o
     #include           stdlib.h




                               @ibaumo
     #include           stdio.h
     #include           semaphore.h
     #include           pthread.h
     #include           unistd.h
     #include           time.h

     #define N hilos 200

     sem t sbanco, scliente;
     int ncliente= 0;

     void ∗cliente(void ∗n){

         int id= ∗(int ∗) n;
         sleep(random() %100);
         printf (Llega el cliente %dn,id);

         sem wait (scliente);
         ncliente++;
         if (ncliente== 1)
           sem wait (sbanco);
         sem post (scliente);

         sleep(random() %3+2); /∗/ tiempo de espera en la cola ∗/
         printf (Se atiende al cliente: %dn, id);
         sleep(random() %3+2); /∗ tiempo invertido en atenderle ∗/

         sem wait (scliente);
         ncliente--;
         printf (Sale el cliente %dn, id);
         if (ncliente== 0)
           sem post (sbanco);


                                                                    121


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         122   100 Ejercicios resueltos de Sistemas Operativos - UJI
sem post (scliente);

    pthread exit(NULL);
}

void ∗furgon (void ∗n) {

    int id= ∗(int ∗) n;

    sleep (random() %100);
    printf (Llega el furgon %dn,id);

    sem wait (sbanco);
    printf   (Se atiende a los guardias %dn, id);
    sleep (random() %5 + 5); /∗ tiempo invertido en atenderlos ∗/
    printf   (Se va el furgon %dn, id);
    sem post (sbanco);

    pthread exit(NULL);
}

int main (int argc, char ∗argv[]) {

    pthread t hilo[N hilos];
    int id[N hilos];
    int i, furgon creado= 0;

    sem init(sbanco, 0, 1);
    sem init(scliente, 0, 1);




                                 @ibaumo
    for (i= 0; i N hilos; i++){
      id[i]= i;
      if(furgon creado== 1)
        pthread create (hilo[i], NULL, cliente, (void ∗)id[i]);
      else
        if (random() %100 95)
           pthread create (hilo[i], NULL, cliente, (void ∗)id[i]);
        else {
          pthread create (hilo[i], NULL, furgon, (void ∗)id[i]);
          furgon creado= 1;
        }
    }

    for (i= 0; i N hilos; i++)
      pthread join (hilo[i],NULL);

    sem destroy(sbanco);
    sem destroy(scliente);

    return 0;
}

Soluci´ n al apartado b):
      o
#include         stdlib.h
#include         stdio.h
#include         semaphore.h
#include         pthread.h
#include         unistd.h
#include         time.h

#define N hilos 200


                                                             122


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   123   100 Ejercicios resueltos de Sistemas Operativos - UJI
sem t sbanco, scliente, sorden;
int ncliente= 0;

void ∗cliente(void ∗n){

    int id= ∗(int ∗) n;
    sleep(random() %100);
    printf (Llega el cliente %dn,id);

    sem wait (sorden);
    sem post (sorden);

    sem wait (scliente);
    ncliente++;
    if (ncliente== 1)
      sem wait (sbanco);
    sem post (scliente);

    sleep(random() %3+2); /∗/ tiempo de espera en la cola ∗/
    printf (Se atiende al cliente: %dn, id);
    sleep(random() %3+2); /∗ tiempo invertido en atenderle ∗/

    sem wait (scliente);
    ncliente--;
    printf (Sale el cliente %dn, id);
    if (ncliente== 0)
      sem post (sbanco);
    sem post (scliente);

    pthread exit(NULL);




                                 @ibaumo
}

void ∗furgon (void ∗n) {

    int id= ∗(int ∗) n;

    sleep (random() %100);
    printf (Llega el furgon %dn,id);

    sem wait (sorden);
    sem wait (sbanco);
    printf   (Se atiende a los guardias %dn, id);
    sleep (random() %5 + 5); /∗ tiempo invertido en atenderlos ∗/
    printf   (Se va el furgon %dn, id);
    sem post (sbanco);
    sem post (sorden);

    pthread exit(NULL);
}

int main (int argc, char ∗argv[]) {

    pthread t hilo[N hilos];
    int id[N hilos];
    int i, furgon creado= 0;

    sem init(sbanco, 0, 1);
    sem init(scliente, 0, 1);
    sem init(sorden, 0, 1);




                                                            123



    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   124   100 Ejercicios resueltos de Sistemas Operativos - UJI
for (i= 0; i N hilos; i++){
            id[i]= i;
            if(furgon creado== 1)
              pthread create (hilo[i], NULL, cliente, (void ∗)id[i]);
            else
              if (random() %100 95)
                 pthread create (hilo[i], NULL, cliente, (void ∗)id[i]);
              else {
                pthread create (hilo[i], NULL, furgon, (void ∗)id[i]);
                furgon creado= 1;
              }
          }

          for (i= 0; i N hilos; i++)
            pthread join (hilo[i],NULL);

          sem destroy(sbanco);
          sem destroy(scliente);
          sem destroy(sorden);

          return 0;
      }



92.   #include          stdio.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          unistd.h
      #include          time.h




                               @ibaumo
      #define MAX 10
      #define N PROD 3
      #define N CONS 2

      int buffer[MAX];

      sem t huecos, elementos, sprod, scon, sfin;
      int pos productor= 0, pos consumidor= 0;
      int cont= 0;

      int generar dato(void)    {return random() %256;}
      int numero aleatorio(void){return random() %100;}

      void ∗productor (void ∗nada) {

          int i, dato, n= numero aleatorio();

          for (i= 0; i n; i++){
            dato= generar dato();
            sleep(random() %2);
            sem wait (huecos);
            sem wait (sprod);
            buffer[pos productor]= dato;
            pos productor= (pos productor+ 1) %MAX;
            sem post (sprod);
            sem post (elementos);
          }

          sem wait (sfin);
          cont++;



                                                                    124


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         125   100 Ejercicios resueltos de Sistemas Operativos - UJI
if (cont== N PROD) /∗ si soy el ultimo productor ∗/
      for (i= 0; i N CONS ; i++){ /∗ por cada consumidor ∗/
        sem wait(huecos);
        buffer[pos productor]= -1;
        pos productor= (pos productor+ 1) %MAX;
        sem post(elementos);
      }
    sem post (sfin);

    pthread exit(NULL);
}


void ∗consumidor(void ∗nada){

    int dato= 0;

    while (dato!= -1) {
      sem wait(elementos);
      sem wait(scon);
      dato= buffer[pos consumidor];
      pos consumidor= (pos consumidor+ 1) %MAX;
      sem post(scon);
      sem post(huecos);
      if (dato!= -1) {
        printf( %d ,dato);
        fflush(stdout);
      }
      sleep(random() %2);
    }




                                 @ibaumo
    pthread exit(NULL);
}

int main(int argc,char ∗argv[]){

    pthread t th[N PROD+N CONS];
    int i=0;

    sem    init      (huecos,0,MAX);
    sem    init      (elementos,0,0);
    sem    init      (sprod,0,1);
    sem    init      (scon,0,1);
    sem    init      (sfin,0,1);

    for (i=0;          i N PROD; i++)
      pthread          create (th[i], NULL, productor, NULL);
    for (i=0;          i N CONS; i++)
      pthread          create (th[i+N PROD], NULL, consumidor, NULL);
    for (i=0;          i N PROD + N CONS; i++)
      pthread          join (th[i], NULL);

    sem    destroy         (huecos);
    sem    destroy         (elementos);
    sem    destroy         (sprod);
    sem    destroy         (scon);
    sem    destroy         (sfin);

    return 0;
}




                                                            125


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   126   100 Ejercicios resueltos de Sistemas Operativos - UJI
93.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          unistd.h
      #include          string.h
      #include          pthread.h
      #include          semaphore.h

      int cont enlaces= 0;
      sem t critico;

      void recorre(char ∗nombredir) {

          DIR ∗d;
          struct dirent ∗entrada;
          struct stat datos;
          char ∗ruta;

          d= opendir(nombredir);
          if (d== NULL) {
            printf(Error al abrir el directorion);
            return;
          }

          entrada= readdir(d);
          while (entrada!= NULL) {
            if (strcmp(entrada-d name,.) 
                strcmp(entrada-d name,..)) {
              ruta= (char ∗)malloc (strlen(nombredir)+




                               @ibaumo
                                        strlen(entrada-d name)+2);
              sprintf(ruta, %s/ %s,nombredir,entrada-d name);
              lstat(ruta,datos);
              if (S ISDIR(datos.st mode)) { /∗ es un directorio? ∗/
                if (datos.st uid== getuid()) /∗ pertenece al usuario? ∗/
                  recorre(ruta);
                else
                  printf ( %s no pertenece al usuarion, ruta);
              } else
              if (S ISLNK(datos.st mode)) { /∗ es un enlace blando? ∗/
                sem wait(critico);
                cont enlaces++;
                sem post(critico);
              }
              free(ruta);
            }
            entrada= readdir(d);
          }
          closedir(d);
      }

      void ∗ busca (void ∗dato) {

          struct stat datos;
          char ∗nombredir= (char ∗)dato;

          lstat (nombredir, datos);
          if (S ISDIR(datos.st mode))
            if (datos.st uid== getuid())
              recorre(nombredir);
            else
              printf ( %s no pertenece al usuarion, nombredir);



                                                                    126

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         127   100 Ejercicios resueltos de Sistemas Operativos - UJI
else
            printf ( %s no es un directorion, nombredir);

          pthread exit(NULL);
      }

      int main(int argc, char ∗argv[]) {

          pthread t hilo[argc-1];
          int i;

          if (argc== 1) {
            printf(Debe especificar al menos un directorion);
            exit(1);
          }

          sem init (critico, 0, 1);
          for (i= 0; i argc-1; i++)
            pthread create (hilo[i], NULL, busca, (void ∗) argv[i+1]);
          for (i= 0; i argc-1; i++)
            pthread join (hilo[i], NULL);

          printf (Enlaces encontrados: %dn, cont enlaces);
          sem destroy (critico);
          return 0;
      }



94.   #include          stdio.h
      #include          stdlib.h




                               @ibaumo
      #include          sys/stat.h
      #include          unistd.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          stdbool.h
      #include          math.h

      int es primo(int numero) {

          int divisor;
          for (divisor=2; divisor= sqrt(numero); divisor++)
            if (numero %divisor==0)
              return 0;
          return 1;
      }

      void productor (int inicio, int fin, int tubo[2], int tubo fin[2]) {

          int numero;
          int contador primos= 0;

          close (tubo[0]);
          close (tubo fin[0]);

          for (numero= inicio; numero= fin; numero++)
            if (es primo(numero)) {
              write (tubo[1], numero, sizeof(int));
              contador primos++;
            }

          close (tubo[1]);
          write (tubo fin[1], contador primos, sizeof(int));


                                                                    127


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         128   100 Ejercicios resueltos de Sistemas Operativos - UJI
close (tubo fin[1]);
}


void consumidor (int tubo[2], int tubo fin[2]) {

    int datos[2];
    int leidos;
    int contador claves= 0;
    bool fin= false;

    close (tubo[1]);
    close (tubo fin[1]);

    while (!fin) {
      leidos= read(tubo[0], datos, 2∗sizeof(int));
      if (leidos== 0) /∗ ya no hay mas datos en la tuberia ∗/
        fin= true;
      else
        if (es primo((datos[0]-1)/2)  es primo((datos[1]-1)/2)) {
          printf (Los numeros %d y %d forman la clave %dn,
            datos[0], datos[1], datos[0]∗datos[1]);
          contador claves++;
        }
    }

    close (tubo[0]);
    read (tubo fin[0], datos, 2∗sizeof(int));
    close (tubo fin[0]);




                                 @ibaumo
    printf (Resumen finaln);
    printf (Se han encontrado %d numeros primos y %d claves criptograficasn,
      datos[0]+datos[1], contador claves);
}

int main (int argc, char∗argv[]) {

    int desde, mitad, hasta;
    int tubo[2], tubo fin[2];

    if (argc!=3) {
      printf (Error, debe especificar el rango de numeros a analizarn);
      exit(1);
    }

    desde= atoi(argv[1]); /∗ se asume que son numeros validos ∗/
    hasta= atoi(argv[2]);
    mitad=(desde+hasta)/2;

    pipe(tubo);
    pipe(tubo fin);

    if (fork()!= 0)
      if (fork()!= 0) {
         consumidor(tubo, tubo fin);
         wait(NULL);
         wait(NULL);
      }
      else
         productor (desde, mitad, tubo, tubo fin);
    else
      productor(mitad+1, hasta, tubo, tubo fin);



                                                            128


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   129        100 Ejercicios resueltos de Sistemas Operativos - UJI
return 0;
      }



95.   #include          stdio.h
      #include          unistd.h
      #include          stdlib.h
      #include          semaphore.h
      #include          pthread.h
      #include          math.h
      #include          stdbool.h

      #define MAX    20
      #define N PROD 2
      #define FIN   -1

      int contador primos= 0;

      sem t critico, elementos, huecos, primos;
      int buffer[MAX];
      int pos productor= 0;

      int es primo(int numero) {

          int divisor;
          for (divisor=2; divisor= sqrt(numero); divisor++)
            if (numero %divisor==0)
              return 0;
          return 1;
      }




                               @ibaumo
      void ∗ productor (void ∗ dato){

          int    ∗data = (int ∗)dato;
          int    numero;
          int    inicio = data[0];
          int    fin =    data[1];

          for (numero= inicio; numero= fin; numero++)
            if (es primo(numero)){
              sem wait(huecos);
              sem wait(critico);
              buffer[pos productor]= numero;
              pos productor=(pos productor+1) %MAX;
              sem post(critico);
              sem post(elementos);
              sem wait(primos);
              contador primos++;
              sem post(primos);
            }

          sem wait(huecos);
          sem wait(critico);
          buffer[pos productor]= FIN;
          pos productor=(pos productor+1) %MAX;
          sem post(critico);
          sem post(elementos);

          pthread exit(NULL);
      }



                                                                    129



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         130   100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗consumidor (void ∗ nada){

    int datos[2];
    int dato,pos consumidor= 0;
    int par= 0;
    bool fin= false;
    int contador claves= 0, cont= 0;

    while (!fin) {
      sem wait(elementos);
      dato=buffer[pos consumidor];
      pos consumidor=(pos consumidor+1) %MAX;
      sem post(huecos);
      if (dato== FIN) {
        cont++;
        if (cont== N PROD)
          fin= true;
      } else {
        if (par %2== 0)
          datos[0]= dato;
        else {
          datos[1]= dato;
          if (es primo((datos[0]-1)/2)  es primo((datos[1]-1)/2)) {
            printf(Los numeros %d y %d forma la clave %dn,
                     datos[0], datos[1], datos[0]∗datos[1]);
            contador claves++;
          }
        }
        par++;
      }




                                 @ibaumo
    }

    printf(Resumen finaln);
    printf(Se han encontrado %d numeros primos y %d claves criptograficasn,
            contador primos, contador claves);

    pthread exit(NULL);
}

int main (int argc,char ∗argv[]) {

    int desde, mitad, hasta;
    pthread t th1,th2,th3;
    int data1[2], data2[2];

    if (argc!= 3){
      printf (Error, debe especificar el rango de numeros a analizarn);
      exit(1);
    }

    desde= atoi(argv[1]); /∗ se asume que los numeros son validos ∗/
    hasta= atoi(argv[2]);
    mitad= (desde+hasta)/2;

    sem    init      (critico,                 0,    1);
    sem    init      (primos,                  0,    1);
    sem    init      (elementos,               0,    0);
    sem    init      (huecos,                  0,    MAX);

    data1[0]= desde;
    data1[1]= mitad;
    data2[0]= mitad+1;



                                                            130


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   131       100 Ejercicios resueltos de Sistemas Operativos - UJI
data2[1]= hasta;
          pthread create (th1, NULL, productor, (void ∗)data1);
          pthread create (th2, NULL, productor, (void ∗)data2);

          pthread create (th3, NULL, consumidor, NULL);

          pthread join (th1,NULL);
          pthread join (th2,NULL);
          pthread join (th3,NULL);

          sem    destroy          (critico);
          sem    destroy          (primos);
          sem    destroy          (elementos);
          sem    destroy          (huecos);

          return 0;
      }



96.   #include          stdio.h
      #include          stdlib.h
      #include          sys/stat.h
      #include          dirent.h
      #include          string.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          unistd.h
      #include          time.h
      #include          fcntl.h




                               @ibaumo
      time t inicio;
      int tubo[2];

      void recorre (char ∗nombredir) {

          DIR ∗d;
          struct dirent ∗entrada;
          struct stat datos;
          char ∗ruta;

          d= opendir (nombredir);
          if (d== NULL) {
            printf(Error al abrir el directorio %sn, nombredir);
            return;
          }

          entrada= readdir(d);
          while (entrada!= NULL) {
            if (strcmp (entrada-d name,.) 
                strcmp (entrada-d name,..)) {
              ruta= malloc (strlen (nombredir)+
                            strlen (entrada-d name)+2);
              sprintf (ruta,  %s/ %s, nombredir, entrada-d name);
              lstat (ruta,datos);
              if (S ISDIR (datos.st mode))
                recorre(ruta);
              else
                if (S ISREG (datos.st mode)) {
                  if ((inicio- datos.st mtime 60∗60) 
                      (datos.st uid== getuid())) {
                    write (tubo[1], ruta, strlen(ruta));
                    write (tubo[1], n, 1);


                                                                    131


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         132   100 Ejercicios resueltos de Sistemas Operativos - UJI
if (fork()== 0)
                                execlp (zip, zip, /tmp/comprimido.zip, ruta, NULL);
                              else
                                wait(NULL);
                     }
                   }
                 free(ruta);
             }
             entrada=readdir(d);
         }
         closedir(d);
     }

     int main (int argc,char ∗argv[]) {

         int fichero;
         inicio= time(NULL);

         if (argc!= 2) {
           printf (Indica un directorio como parametron);
           exit(0);
         }

         pipe(tubo);
         if (fork()== 0){
           close   (tubo[0]);
           recorre (argv[1]);
           close   (tubo[1]);
         } else {
           fichero= creat (usuario.log, 00644);




                               @ibaumo
           dup2 (fichero, STDOUT FILENO);
           dup2 (tubo[0], STDIN FILENO);
           close (fichero);
           close (tubo[0]);
           close (tubo[1]);
           execlp (sort, sort, NULL);
         }

         exit(0);
     }


97. La soluci´ n que se presenta a continuaci´ n incluye los dos puntos indicados
             o                               o
    en el enunciado donde el sem´ foro orden se ha utilizado para resolver el
                                    a
    segundo punto.
     #include           stdio.h
     #include           stdlib.h
     #include           semaphore.h
     #include           pthread.h
     #include           unistd.h
     #include           sys/syscall.h

     #define N atletas 30

     sem t instalaciones, corredores, orden;
     int cont= 0;

     void ∗corredor (void ∗ nada) {

         int n= (int) syscall(SYS gettid);



                                                                    132


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         133      100 Ejercicios resueltos de Sistemas Operativos - UJI
sem wait(orden);
    printf (Llega corredor: %dn, n);
    sem wait(corredores);
    cont++;
    if (cont== 1)
      sem wait(instalaciones);
    printf (Entra en las instalaciones el corredor %dn, n);
    sem post(corredores);
    sem post(orden);

    sleep(random() %3); /∗ tiempo invertido en usarlas ∗/

    sem wait(corredores);
    cont--;
    printf (Sale de las instalaciones el corredor: %dn, n);
    if (cont== 0)
      sem post(instalaciones);
    sem post(corredores);

    pthread exit(NULL);
}

void ∗jabalino (void ∗ nada) {

    int n= (int) syscall(SYS gettid);

    sem wait(orden);
    printf (Llega lanzador de jabalina: %dn, n);
    sem wait(instalaciones);
    printf (Entra en las instalaciones el jabalino %dn, n);




                                 @ibaumo
    sleep(random() %3+2); /∗ tiempo invertido en usarlas ∗/
    printf (Sale de las instalaciones el jabalino: %dn, n);
    sem post(instalaciones);
    sem post(orden);

    pthread exit(NULL);
}

void ∗martillo (void ∗ nada) {

    int n= (int) syscall(SYS gettid);

    sem wait(orden);
    printf (Llega lanzador de martillo: %dn, n);
    sem wait(instalaciones);
    printf (Entra en las instalaciones el martillo %dn, n);
    sleep(random() %3+2); /∗ tiempo invertido en usarlas ∗/
    printf (Sale de las instalaciones el martillo: %dn, n);
    sem post(instalaciones);
    sem post(orden);

    pthread exit(NULL);
}

int main (int argc, char ∗argv[]) {

    int num;
    pthread t th[N atletas];

    sem init (instalaciones, 0, 1);
    sem init (corredores, 0, 1);
    sem init (orden, 0, 1);



                                                            133


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   134   100 Ejercicios resueltos de Sistemas Operativos - UJI
for (num= 0; num N atletas; num++) {
            sleep(random() %3);
            if (random() %100  66)
              pthread create (th[num], NULL, corredor, NULL);
            else
              if (random() %100  82)
                 pthread create (th[num], NULL, jabalino, NULL);
              else
                pthread create (th[num], NULL, martillo, NULL);
          }

          for (num= 0; num N atletas; num++)
            pthread join(th[num], NULL);

          sem destroy (instalaciones);
          sem destroy (corredores);
          sem destroy (orden);

          return 0;
      }



98.   #include          stdio.h
      #include          stdlib.h
      #include          unistd.h
      #include          time.h
      #include          pthread.h
      #include          string.h
      #include          semaphore.h




                               @ibaumo
      #define NHILOS 100
      #define PAISES 10

      typedef struct {
        int pais;
        int valor;
      } params;

      char paises[PAISES][30]={ Espa˜ a, Portugal, Francia,
                                           n
      Ucrania, Letonia, Servia, Israel, Alemania, Italia, Holanda};
      int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0};
      sem t srecurso[PAISES],sjurado;
      int njurados= 0;

      void ∗voto (void ∗dato) {

          params ∗mi dato= (params∗) dato;
          int pais= mi dato-pais;
          int puntos=mi dato-valor;

          sleep(random() %2);

          sem wait(srecurso[pais]);
          printf (Voto al pais %s %d puntosn, paises[pais],puntos);
          puntuaciones[pais]+= puntos;
          printf (Ya he votado al pais %s %d puntosn, paises[pais],puntos);
          sem post(srecurso[pais]);

          pthread exit(NULL);
      }



                                                                    134



  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         135   100 Ejercicios resueltos de Sistemas Operativos - UJI
void ∗consulta (void ∗dato) {

    int pais= ∗(int∗)dato, num;

    sleep(random() %2);

    sem wait(sjurado);
    njurados++;
    if (njurados== 1)
      for (num= 0; num PAISES; num++)
        sem wait(srecurso[num]);
    printf(El pais %d realiza la consultan, pais);
    sem post(sjurado);

    for (num= 0; num PAISES; num++)
      printf (( %s, %d)n, paises[num], puntuaciones[num]);

    sem wait(sjurado);
    njurados--;
    printf (El pa´s %d termina la consultan, pais);
                  ı
    if (njurados== 0)
      for (num= 0; num PAISES; num++)
        sem post (srecurso[num]);
    sem post(sjurado);

    pthread exit(NULL);
}

int main (int argc,char ∗argv[]) {




                                 @ibaumo
    pthread t hilo[NHILOS];
    int num, pais, idPais[NHILOS];
    params unvoto[NHILOS];

    for (num= 0; num PAISES; num++)
      sem init (srecurso[num], 0, 1);
    sem init (sjurado, 0, 1);

    for (num= 0; num NHILOS; num++){
      pais= random() %PAISES;
      if (random() %100  90) {
        unvoto[num].pais= pais;
        unvoto[num].valor= random() %10;
        pthread create (hilo[num], NULL, voto, (void ∗)unvoto[num]);
      } else {
        idPais[num]= pais;
        pthread create (hilo[num], NULL,
                         consulta, (void ∗)idPais[num]);
      }
    }

    for (num= 0; num NHILOS; num++)
      pthread join(hilo[num],NULL);

    for (num=0; num PAISES; num++)
      sem destroy(srecurso[num]);
    sem destroy(sjurado);

    return 0;
}




                                                            135


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   136   100 Ejercicios resueltos de Sistemas Operativos - UJI
99.   #include          stdio.h
      #include          stdlib.h
      #include          unistd.h
      #include          sys/types.h
      #include          sys/wait.h
      #include          string.h

      #define N 100
      #define PAISES 10

      char paises[PAISES][10]={Espa˜ a, Portugal, Francia, Ucrania,
                                          n
      Letonia, Servia, Israel, Alemania, Italia, Holanda};
      int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0};

      int main (int argc,char ∗argv[]) {

         int num, dato[2];
         int tubA[2],tubB[2];
         char ∗linea;

         pipe(tubA);

         for (num= 0; num N; num++){
           if (fork()== 0){
             srandom (getpid());
             dato[0]= random() %PAISES;
             dato[1]= random() %10;
             printf (Soy el votante %d, mi voto es para el pais %d %d puntosn,
                      num, dato[0], dato[1]);
             close (tubA[0]);




                               @ibaumo
             write (tubA[1], dato, 2∗sizeof(int));
             close (tubA[1]);
             exit (0);
           }
         }

         close (tubA[1]);
         while (read (tubA[0], dato, 2∗sizeof(int)))
           puntuaciones[dato[0]]+= dato[1];
         close (tubA[0]);

         printf(La votacion resultante es:n);
         printf((pais,numero de votos)n);
         for (num= 0; num PAISES; num++)
           printf (( %s, %d)n, paises[num], puntuaciones[num]);

         pipe(tubB);

         if (fork()!= 0) {
           close (tubB[0]);
           for (num= 0; num PAISES; num++){
              linea= (char∗) malloc (strlen (paises[num])+ 15);
              sprintf (linea,  %3d puntos, %sn,
                       puntuaciones[num], paises[num]);
              write (tubB[1], linea, strlen(linea));
              free (linea);
           }
           close (tubB[1]);
         } else {
             dup2   (tubB[0],STDIN FILENO);
             close (tubB[1]);
             close (tubB[0]);



                                                                    136

  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         137       100 Ejercicios resueltos de Sistemas Operativos - UJI
execlp (sort, sort, -r, NULL);
            }

            for (num= 0; num N+1; num++)
              printf (Fin del proceso de PID %d.n, wait(NULL));

            return 0;
        }



100.    #include          stdio.h
        #include          stdlib.h
        #include          sys/stat.h
        #include          dirent.h
        #include          unistd.h
        #include          string.h
        #include          sys/types.h
        #include          sys/wait.h

        int cuenta= 0, tubo1[2], tubo2[2];

        void recorre (char ∗nombredir) {

            DIR ∗d;
            struct dirent ∗entrada;
            struct stat datos;
            char ∗ruta;
            char dato[10];

            d= opendir(nombredir);




                               @ibaumo
            if (d== NULL) return;

            entrada= readdir(d);
            while (entrada!=NULL) {
              if (strcmp(entrada-d name, .) 
                  strcmp(entrada-d name, ..)) {
                ruta= malloc (strlen(nombredir)+ strlen(entrada-d name)+2);
                sprintf (ruta,  %s/ %s, nombredir, entrada-d name);
                lstat (ruta, datos);
                if (S ISDIR(datos.st mode))
                  recorre (ruta);
                else
                  if (datos.st blocks 1024) {
                     sprintf (dato,  %ldn, (long int)datos.st ino);
                    write (tubo1[1], dato, strlen(dato));
                    cuenta++;
                  }
                free(ruta);
              }
              entrada= readdir(d);
            }
            closedir (d);
        }

        int main (int argc, char ∗argv[]) {

            int num, dato, total= 0;

            pipe(tubo1);
            pipe(tubo2);




                                                                    137


  J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7         138   100 Ejercicios resueltos de Sistemas Operativos - UJI
for (num= 1; num argc; num++)
      if (fork()== 0) { /∗ procesos de busqueda ∗/
        close (tubo1[0]);
        close (tubo2[0]);
        recorre (argv[num]);
        write (tubo2[1], cuenta, sizeof(int));
        close (tubo1[1]);
        close (tubo2[1]);
        exit(0);
      }
    if (fork()== 0) { /∗ proceso de ordenacion ∗/
      dup2 (tubo1[0], STDIN FILENO);
      close (tubo1[0]);
      close (tubo1[1]);
      close (tubo2[0]);
      close (tubo2[1]);
      execlp (sort, sort, NULL);
    }

    close (tubo1[0]); /∗ proceso principal ∗/
    close (tubo1[1]);
    close (tubo2[1]);
    while (read (tubo2[0], dato, sizeof(int))!= 0)
      total+= dato;
    close(tubo2[0]);

    for (num= 0; num argc; num++)
      wait(NULL);

    printf (Total de ficheros encontrados %dn, total);




                                 @ibaumo
    return 0;
}




                                                            138


    J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7   139   100 Ejercicios resueltos de Sistemas Operativos - UJI

Más contenido relacionado

PDF
100 Ejerc...
PDF
Introducción a la Informática
DOCX
IteraciónI.FaseConstruccion
PPT
Procesos
PDF
SlideShare 101
PDF
Curso programación y_métodos_numéricos_linux
PDF
52811100 manual-sp
100 Ejerc...
Introducción a la Informática
IteraciónI.FaseConstruccion
Procesos
SlideShare 101
Curso programación y_métodos_numéricos_linux
52811100 manual-sp

Similar a Fundamentos Computadores II (20)

PDF
Modelo gestion preventiva
PDF
Conselleria educació pmb_bibliotecas
PDF
Comandos cisco ccna_exploration
PDF
Comandos cisco ccna_exploration
PDF
Comandos cisco ccna_exploration
PDF
Manual guadalinex edu
PDF
Tutorial de maxima
PDF
Texto de matematicas 2009-2011
PDF
Informe Biocat 2011 (resumen ejecutivo en castellano)
PDF
Manual Scilab
PDF
Manualscilab 090513151714 Phpapp02
PDF
Manual de rutinas informaticas
DOCX
Manual de todos listo
PDF
Diseño de Experimentos
PDF
100 ejercicios-resueltos-de-sistemas-operativos
PDF
Material MAT021
PDF
Tercer año
PDF
Manual de latex
PDF
Introduccion a la programacion en c prev
Modelo gestion preventiva
Conselleria educació pmb_bibliotecas
Comandos cisco ccna_exploration
Comandos cisco ccna_exploration
Comandos cisco ccna_exploration
Manual guadalinex edu
Tutorial de maxima
Texto de matematicas 2009-2011
Informe Biocat 2011 (resumen ejecutivo en castellano)
Manual Scilab
Manualscilab 090513151714 Phpapp02
Manual de rutinas informaticas
Manual de todos listo
Diseño de Experimentos
100 ejercicios-resueltos-de-sistemas-operativos
Material MAT021
Tercer año
Manual de latex
Introduccion a la programacion en c prev
Publicidad

Más de Iván BM (8)

PDF
Modem GSM Wavecom Fastrack
PDF
Trabajo sobre el protocolo Spdy
PDF
Ieee802 11n iván_bautista_moreno
PDF
Ieee802 11n iván_bautista_moreno
PDF
Exp. IBM
PDF
Cartel curso latex lyx
PDF
Resumen transporte de datos
PDF
Wigig, Wi-Fi & WiMaX
Modem GSM Wavecom Fastrack
Trabajo sobre el protocolo Spdy
Ieee802 11n iván_bautista_moreno
Ieee802 11n iván_bautista_moreno
Exp. IBM
Cartel curso latex lyx
Resumen transporte de datos
Wigig, Wi-Fi & WiMaX
Publicidad

Último (20)

PDF
Gasista de unidades unifuncionales - pagina 23 en adelante.pdf
PDF
COMPLETO__PROYECTO_VIVAN LOS NIÑOS Y SUS DERECHOS_EDUCADORASSOS.pdf
PDF
Como Potenciar las Emociones Positivas y Afrontar las Negativas Ccesa007.pdf
PPTX
Welcome to the 8th Physical Science Class 2025-2026
PDF
Habitos de Ricos - Juan Diego Gomez Ccesa007.pdf
PDF
Crear o Morir - Andres Oppenheimer Ccesa007.pdf
DOCX
Informe_practica pre Final.docxddadssasdddddddddddddddddddddddddddddddddddddddd
PDF
Didactica de la Investigacion Educativa SUE Ccesa007.pdf
PDF
Unidad de Aprendizaje 5 de Educacion para el Trabajo EPT Ccesa007.pdf
PDF
Mi Primer Millon - Poissant - Godefroy Ccesa007.pdf
PPTX
Presentación de la Cetoacidosis diabetica.pptx
PDF
Unidad de Aprendizaje 5 de Matematica 1ro Secundaria Ccesa007.pdf
PPTX
Doctrina 1 Soteriologuia y sus diferente
DOCX
PLAN DE CASTELLANO 2021 actualizado a la normativa
DOCX
V UNIDAD - SEGUNDO GRADO. del mes de agosto
PPTX
Welcome to the 7th Science Class 2025-2026 Online.pptx
PDF
2.0 Introduccion a processing, y como obtenerlo
PDF
Cronograma de clases de Práctica Profesional 2 2025 UDE.pdf
PDF
Fundamentos_Educacion_a_Distancia_ABC.pdf
PDF
Teologia-Sistematica-Por-Lewis-Sperry-Chafer_060044.pdf
Gasista de unidades unifuncionales - pagina 23 en adelante.pdf
COMPLETO__PROYECTO_VIVAN LOS NIÑOS Y SUS DERECHOS_EDUCADORASSOS.pdf
Como Potenciar las Emociones Positivas y Afrontar las Negativas Ccesa007.pdf
Welcome to the 8th Physical Science Class 2025-2026
Habitos de Ricos - Juan Diego Gomez Ccesa007.pdf
Crear o Morir - Andres Oppenheimer Ccesa007.pdf
Informe_practica pre Final.docxddadssasdddddddddddddddddddddddddddddddddddddddd
Didactica de la Investigacion Educativa SUE Ccesa007.pdf
Unidad de Aprendizaje 5 de Educacion para el Trabajo EPT Ccesa007.pdf
Mi Primer Millon - Poissant - Godefroy Ccesa007.pdf
Presentación de la Cetoacidosis diabetica.pptx
Unidad de Aprendizaje 5 de Matematica 1ro Secundaria Ccesa007.pdf
Doctrina 1 Soteriologuia y sus diferente
PLAN DE CASTELLANO 2021 actualizado a la normativa
V UNIDAD - SEGUNDO GRADO. del mes de agosto
Welcome to the 7th Science Class 2025-2026 Online.pptx
2.0 Introduccion a processing, y como obtenerlo
Cronograma de clases de Práctica Profesional 2 2025 UDE.pdf
Fundamentos_Educacion_a_Distancia_ABC.pdf
Teologia-Sistematica-Por-Lewis-Sperry-Chafer_060044.pdf

Fundamentos Computadores II

  • 2. 100 Ejercicios resueltos @ibaumo de Sistemas Operativos José Ribelles Miguel José Martínez Sotoca Pedro García Sevilla Departament de llenguatges i sistemes informàtics Codi d’assignatura IG11 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 3. @ibaumo Edita: Publicacions de la Universitat Jaume I. Servei de Comunicació i Publicacions Campus del Riu Sec. Edifici Rectorat i Serveis Centrals. 12071 Castelló de la Plana http://www.tenda.uji.es e-mail: publicacions@uji.es Col·lecció Sapientia, 30 www.sapientia.uji.es ISBN: 978-84-693-0148-7 Aquest text està subjecte a una llicència Reconeixement-NoComercial-CompartirIgual de Creative Commons, que permet copiar, distribuir i comunicar públicament l’obra sempre que especifique l’autor i el nom de la publicació i sense objectius comercials, i també permet crear obres derivades, sempre que siguen distribuïdes amb aquesta mateixa llicència. http://creativecommons.org/licenses/by-nc-sa/2.5/es/deed.ca J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 4. ´ Indice general ´ Indice general Prefacio 4 1. Procesos e Hilos 1 1.1. Procesos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1. 1.2. Planificaci´ n . . Procesos e Hiloso . . . . . . . . . . . . . . . . . . . . . . . . . . 18 6 1.3. Hilos . . . .. . . . .. 1.1. Procesos .. .. . . .. .. .. . . . .. .. .. . . .. .. .. . . . .. .. .. . . .. .. .. . . . . . 13 . . 6 1. 1.2. Planificaci´ n . . . . . . . . . . . . o 2. Comunicaci´ n y Sincronizaci´ n de Procesos o o . . . . . . . . . . . . . 15 . . 13 8 . 1.3. Tuber´as. .. .. . . . .. .. .. . .. .. .. . . . .. .. .. . .. 2.1. Hilos ı . . .. .. . . . .. .. .. . .. .. .. . . . . . 15 . . 1813 . . 2.2. Sem´ foros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a 19 2. Comunicaci´ n y Sincronizaci´ n de Procesos o o 2015 3. Gesti´ n de Archivos y Directorios . . . . . . . . . . . . . . . . . . . 29 . . 2015 2.1. o Tuber´as . . . . . . . . . ı . 3.1. Sistemas de Archivos . .. .. .. . . . .. .. .. . .. .. .. . . . .. .. .. . .. .. .. . . . . . 29 . . 2419 2.2. Sem´ foros . . . . a . . . . 3.2. Archivos y Directorios . . . . . . . . . . . . . . . . . . . . . . . 31 3. Gesti´ n de Archivos y Directorios o 33 29 4. Gesti´ n de Memoria o 35 @ibaumo 3.1. Sistemas de Archivos . . . . . . . . . . . . . . . . . . . . . . . . 3329 4.1. Paginaci´ n . . . . . . . . . . . . . o . . . . . . . . . . . . . . . . . 35 3.2. Pol´ticas de y Directorios. .. . . . .. 4.2. Archivos Reemplazo . ı .. .. . . .. .. .. . . . .. .. .. . .. . .. .. . . . . . 36 . . 3531 . 5. Ejerciciosde Memoria 4. Gesti´ n Generales o 3835 39 4.1. Paginaci´ n . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3835 o 6. Solucionesıticas de Reemplazo . . . . . . . . . . . . . . . . . . . . 57 . . 4.2. Pol´ . 3936 5. Ejercicios Generales 4139 6. Soluciones 5857 V V J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 5. Prefacio Los Sistemas Operativos han constituido tradicionalmente una materia troncal en los planes de estudio de todas las titulaciones de Inform´ tica. Las asignaturas a que desarrollan estos contenidos incluyen aspectos te´ ricos fundamentales como o procesos e hilos, gesti´ n de memoria, comunicaci´ n, sincronizaci´ n y sistemas de o o o archivos. Adem´ s, es frecuente incluir una parte pr´ ctica que permite que el alumno a a conozca no s´ lo los principios te´ ricos, sino tambi´ n c´ mo se aplican en sistemas o o e o operativos reales. El objetivo de este libro es proporcionar suficiente material pr´ ctico para apo- a yar la docencia, tanto presencial, desarrollada en clases de problemas o en labo- ratorio, como no presencial, proporcionando al estudiante un material de apoyo al estudio de un nivel y contenido adecuado a una asignatura real. @ibaumo En concreto, las cuestiones, ejercicios y problemas que se recogen en este li- bro son el resultado de su recopilaci´ n a lo largo de cuatro cursos, desde el a˜ o o n 2004, del material utilizado en la asignatura de Sistemas Operativos de la Inge- nier´a T´ cnica en Inform´ tica de Gesti´ n de la Universitat Jaume I de Castell´ n. ı e a o o Dicha asignatura se estructura en 3 cr´ ditos de teor´a, 1,5 cr´ ditos de problemas y e ı e 1,5 cr´ ditos de laboratorio. No obstante, el material incluido es bastante gen´ rico e e y puede ser empleado en cualquier asignatura b´ sica de Sistemas Operativos. a El contenido de este libro se divide en 6 cap´tulos cuya descripci´ n se indica a ı o continuaci´ n: o 1. Gesti´ n de Procesos e Hilos: planificaci´ n de procesos, jerarqu´a de procesos o o ı y uso de las llamadas al sistema para la gesti´ n de procesos e hilos. o 2. Comunicaci´ n y Sincronizaci´ n de Procesos: problemas cl´ sicos de la sec- o o a ci´ n cr´tica, productor-consumidor y lector-escritor; y llamadas al sistema o ı para el manejo de sem´ foros y tuber´as. a ı 3. Gesti´ n de Archivos y Directorios: sistemas de archivos tipo FAT y nodo-i, o llamadas al sistema para la gesti´ n de archivos y directorios. o 4. Gesti´ n de Memoria: memoria virtual, paginaci´ n y pol´ticas de reemplazo. o o ı 5. Problemas generales: problemas cuya resoluci´ n incluya conceptos tratados o en varios de los cap´tulos anteriores. ı III J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 6. 6. Soluciones: en este cap´tulo se encuentran las soluciones a los ejercicios ı planteados en todos los cap´tulos anteriores. ı Se ha creado la p´ gina Web http://ig11.uji.es como apoyo a este ma- a terial, para mantenerlo actualizado incluyendo m´ s ejercicios, p´ ginas de ayuda, fe a a de erratas, etc. ´ Por ultimo, no queremos dejar de expresar nuestro agradecimiento a los pro- fesores Gustavo Casa˜ , Isabel Gracia y Antonio Castellanos, todos ellos del De- n partamento de Lenguajes y Sistemas Inform´ ticos de la Universitat Jaume I, que a tambi´ n han participado en la impartici´ n de la asignatura durante otros cursos y, e o como no, en la elaboraci´ n de algunos de los ejercicios propuestos de este libro. o Marzo, 2010 @ibaumo J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 7. Cap´tulo 1 ı Procesos e Hilos 1.1. Procesos 1. Observa el siguiente c´ digo y escribe la jerarqu´a de procesos resultante. o ı #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h @ibaumo int main (int argc, char ∗argv[]) { int num; pid t pid; for (num= 0; num 3; num++) { pid= fork(); printf (Soy el proceso de PID %d y mi padre tiene %d de PID.n, getpid(), getppid()); if (pid!= 0) break; srandom(getpid()); sleep (random() %3); } if (pid!= 0) printf (Fin del proceso de PID %d.n, wait (NULL)); return 0; } Ahora compila y ejecuta el c´ digo para comprobarlo. Contesta a las siguien- o tes preguntas: ¿Por qu´ aparecen mensajes repetidos? e Presta atenci´ n al orden de terminaci´ n de los procesos, o o • ¿qu´ observas? e • ¿por qu´ ? e 1 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 8. 2. Observa el siguiente c´ digo y escribe la jerarqu´a de procesos resultante. o ı #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h int main (int argc, char ∗argv[]) { int num; pid t pid; srandom(getpid()); for (num= 0; num 3; num++) { pid= fork(); printf (Soy el proceso de PID %d y mi padre tiene %d de PID.n, getpid(), getppid()); if (pid== 0) break; } if (pid== 0) sleep(random() %5); else for (num= 0; num 3; num++) printf (Fin del proceso de PID %d.n, wait (NULL)); return 0; } @ibaumo Ahora compila y ejecuta el c´ digo para comprobarlo. Presta atenci´ n al or- o o den de terminaci´ n de los procesos, ¿qu´ observas? ¿por qu´ ? o e e ´ 3. Dibuja la estructura del arbol de procesos que obtendr´amos al ejecutar el ı siguiente fragmento de c´ digo: o for (num= 0; num 2; num++) { nuevo= fork(); /∗ 1 ∗/ if (nuevo== 0) break; } nuevo= fork(); /∗ 2 ∗/ nuevo= fork(); /∗ 3 ∗/ printf(Soy el proceso %d y mi padre es %dn, getpid(), getppid()); 4. Considerando el siguiente fragmento de c´ digo: o for (num= 1; num= n; num++){ nuevo= fork(); if ((num== n) (nuevo== 0)) execlp (ls, ls, -l, NULL); } a) Dibuja la jerarqu´a de procesos generada cuando se ejecuta y n es 3. ı b) Indica en qu´ procesos se ha cambiado la imagen del proceso usando e la funci´ n execlp. o 2 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 9. 5. Dibuja la jerarqu´a de procesos que resulta de la ejecuci´ n del siguiente c´ di- ı o o go. Indica para cada nuevo proceso el valor de las variables i y j en el mo- mento de su creaci´ n. o for (i= 0; i 2; i++) { pid= getpid(); for (j= 0; j i+2; j++) { nuevo= fork(); /∗ 1 ∗/ if (nuevo!= 0) { nuevo= fork(); /∗ 2 ∗/ break; } } if (pid!= getpid()) break; } 6. Estudia el siguiente c´ digo y escribe la jerarqu´a de procesos resultante. Des- o ı pu´ s, compila y ejecuta el c´ digo para comprobarlo (deber´ s a˜ adir llamadas e o a n al sistema getpid, getppid y wait para conseguirlo). #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h #define L1 2 #define L2 3 @ibaumo int main (int argc, char ∗argv[]) { int cont1, cont2; pid t pid; for (cont2= 0; cont2 L2; cont2++) { for (cont1= 0; cont1 L1; cont1++) { pid= fork(); if (pid== 0) break; } if (pid!= 0) break; } return 0; } 7. Dibuja la jerarqu´a de procesos que resulta de la ejecuci´ n del siguiente c´ di- ı o o ´ go. Introduce las llamadas al sistema wait para que una vez generado el arbol de procesos los hijos sean esperados por sus respectivos padres. Adem´ s, a haz que se informe de los tiempos de ejecuci´ n de las aplicaciones xload y o kcalc que se generen as´ como del tiempo total de ejecuci´ n. Para calcular el ı o tiempo transcurrido, puedes utilizar la funci´ n time() de la librer´a est´ ndar o ı a time.h. La llamada time(NULL) devuelve los segundos transcurridos desde las 00:00:00 del 1/1/1970 hasta el instante de la llamada. 3 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 10. int main (int argc, char ∗argv[]) { int i, j; pid t pid, nuevo, nuevo1; time t ini, fin; for (i= 0; i 2; i++){ pid= getpid(); for (j= 0; j i+2; j++){ nuevo= fork(); if(nuevo== 0){ break; nuevo1= fork(); if(nuevo1== 0) execlp (xload, xload, NULL); } } if (pid!= getpid()) execlp (kcalc, kcalc, NULL); } return 0; } ´ 8. Escribe un programa que genere un arbol de procesos similar al que apa- ´ rece en la figura 1.1. Los valores de profundidad y anchura del arbol ser´ n a dados como par´ metros de entrada por el usuario en cada ejecuci´ n. En el a o ejemplo, se considera que la profundidad es 5 y la anchura 3. Tu programa @ibaumo podr´ empezar, por ejemplo, de la siguiente manera: a #include stdio.h #include unistd.h #include stdlib.h int main (int argc, char ∗argv[]) { int i; int prof, anch; if (argc!= 3) exit(0); profundidad= atoi(argv[1]); /∗ profundidad ∗/ anchura= atoi(argv[2]); /∗ anchura ∗/ /∗ completar aqu´ ∗/ ı printf(Soy el proceso %d y mi padre es %dn, getpid(), getppid()); sleep (2); return 0; } ´ Modifica el programa anterior para que la expansi´ n en anchura del arbol se o produzca s´ lo en aquellos niveles de profundidad par (y distinta de cero). En o la figura 1.2 se muestra un ejemplo. 9. Escribe el fragmento de c´ digo que genera la jerarqu´a de procesos que se o ı muestra en la figura 1.3 para profundidad n. 4 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 11. ´ Figura 1.1: Arbol de profun- ´ Figura 1.2: Arbol de profun- didad 5 y anchura 3. didad 5 y anchura 3, que s´ lo o se expande en anchura para los niveles pares distintos de cero. @ibaumo Figura 1.3: Jerarqu´a de procesos con profundidad n = 3. ı 10. Observa el siguiente fragmento de c´ digo que trata de medir el tiempo de o ejecuci´ n del programa prueba.exe. Indica qu´ problemas se producen, por o e qu´ y c´ mo resolverlos. e o time t inicio= 0, fin= 0; if (fork()!= 0) { wait (NULL); fin= time (NULL); printf (Tiempo empleado: %ldn, fin-inicio); } else { inicio= time (NULL); execlp (prueba.exe, prueba.exe, NULL); } 11. El programa siguiente pretende lanzar a ejecuci´ n una calculadora, kcalc, y o otra aplicaci´ n, xload, utilizando dos llamadas al sistema execlp consecuti- o vas. Antes de compilar y ejecutar el programa, piensa qu´ va a ocurrir. e #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h 5 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 10 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 12. int main (int argc, char ∗argv[]) { execlp (kcalc, kcalc, NULL); printf (¿Se imprimira este mensaje?n); execlp (xload, xload, NULL); printf (¿Y este otro?n); return 0; } Ahora, comp´lalo y ejecut´ lo y observa qu´ ocurre. ¿Has acertado? ¿Sabes ı a e por qu´ ? Modif´calo para que el usuario vea las dos aplicaciones al mismo e ı tiempo. Haz adem´ s que el proceso principal espere a la finalizaci´ n de am- a o bas aplicaciones e informe de la finalizaci´ n de cada una especificando si o termin´ kcalc o xload. o 12. A˜ ade al programa resultado del problema 11 el c´ lculo del tiempo que cada n a uno de los procesos ha estado en ejecuci´ n, incluido el proceso padre, y sea o el proceso padre el que informe de ellos antes de finalizar. 13. Escribe un programa en C que pida por teclado dos cadenas de caracteres y despu´ s escriba cada cadena por pantalla car´ cter a car´ cter. La escritura de e a a cada cadena deber´ hacerla un proceso diferente. Recuerda utilizar la funci´ n a o fflush despu´ s de escribir cada car´ cter. El proceso padre deber´ esperar a e a a que termine el proceso hijo. Obtendr´ s resultados interesantes si despu´ s de a e escribir cada car´ cter introduces un retardo aleatorio para simular que su a @ibaumo escritura consume un cierto tiempo. 14. El siguiente programa en C lee repetidamente por teclado el nombre de un programa a ejecutar y pregunta si se debe esperar a que termine la ejecuci´ n o del mismo. El programa termina de ejecutarse cuando el usuario introduce como programa a ejecutar salir. #include stdio.h #include string.h #include stdbool.h int main (int argc, char ∗argv[]) { bool fin= false; char nombre prog[50], esperar[5]; while (!fin) { printf (Programa: ); scanf ( %s, nombre prog); if (strcmp(nombre prog, salir)!=0) { printf (Esperar? ); scanf ( %s, esperar); /∗ completar aqu´ ∗/ ı } else fin= true; } return 0; } 6 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 11 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 13. Realiza las modificaciones oportunas para que el programa cree un nuevo proceso que se encargue de ejecutar el programa indicado. Se debe utilizar la variable PATH para buscar el programa a ejecutar. Si dicho programa no se pudiese ejecutar por cualquier motivo, se deber´ mostrar un mensaje de a error e informar al usuario del valor actual de la variable PATH. En cualquier caso, el proceso inicial esperar´ o no la finalizaci´ n del programa dado en a o funci´ n de lo que el usuario haya indicado. Cuando no se espere la finaliza- o ci´ n del programa dado, se debe indicar el identificador del proceso creado. o Para comprobar el correcto funcionamiento de este programa se aconseja es- cribir otro programa que muestre por pantalla los n´ meros del 1 al 20 con u ´ un intervalo de 1 segundo entre cada n´ mero. Pide que sea este el programa u que se ejecute, unas veces esperando su finalizaci´ n y otras no. o 15. El siguiente programa recibe como par´ metro de entrada un n´ mero entero a u y muestra como resultado su factorial. #include stdio.h #include stdlib.h #include unistd.h long long int factorial (int n) { long long int resultado= 1; int num; @ibaumo for (num= 2; num= n; num++) { resultado= resultado∗ num; printf (Factorial de %d, resultado parcial %lldn, n, resultado); sleep (random() %3); } return resultado; } int main (int argc, char ∗argv[]) { if (argc== 2) printf (El factorial de %s es %lldn, argv[1], factorial (atoi (argv[1]))); return 0; } a) Escr´belo, comp´lalo y ejec´ talo para comprobar su funcionamiento. ı ı u b) Escribe un nuevo programa que reciba dos n´ meros enteros como par´ me- u a tros de entrada y cree dos procesos de manera que cada uno calcule el factorial de uno de los n´ meros, de forma concurrente, y utilizando el u fichero ejecutable obtenido en el apartado anterior. ´ c) Haz que el proceso padre sea el ultimo en terminar, es decir, que espere a la terminaci´ n de sus procesos hijos. o 16. Generaliza la soluci´ n del problema 15 de manera que no est´ limitado a 2 o e el n´ mero de factoriales a calcular. Procede de la siguiente manera: u 7 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 12 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 14. a) Crea un proceso por cada factorial a calcular, y que todos los procesos se ejecuten de forma concurrente. b) El proceso padre deber´ esperar a todos los procesos hijos y mostrar un a mensaje a medida que vayan terminando indicando el PID del proceso finalizado. c) Modif´calo para que no se imprima mensaje cuando el primer proceso ı hijo finalice, pero si para los dem´ s. a 17. Escribe un programa, al que llamar´ s tiempo.c, cuyo objetivo es lanzar a eje- a o a ı ´ cuci´ n un segundo programa que ser´ indicado en la l´nea de ordenes (junto con sus argumentos) como por ejemplo: $ tiempo ls -R -l /tmp. Adem´ s, haz a que se contabilice de forma aproximada el tiempo que tarda en ejecutarse el segundo programa. 1.2. Planificaci´ n o Para la realizaci´ n de los siguientes ejercicios ten en cuenta que: o La simulaci´ n comienza siempre con una interrupci´ n de reloj. o o Cuando un proceso cambia su estado de bloqueado a listo, y si en el enun- ciado no se indica nada al respecto, el proceso se situar´ siempre al final de a @ibaumo la cola de espera. 18. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. La interrupci´ n de reloj se produce cada 4 unidades de tiempo. o Las rutinas de tratamiento de las interrupciones hardware y de la inte- rrupci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamien- o to de la interrupci´ n software consume 2 unidades de tiempo. o Existen dos dispositivos de entrada/salida sobre los que se pueden rea- lizar operaciones en paralelo. Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo 1 a o (IH1) - Nivel 1: Interrupci´ n de reloj (IR) o - Nivel 2: Interrupci´ n hardware del dispositivo 2 (IH2) o - Nivel 3 (menos prioritario): Interrupci´ n software (IS) o Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini- a cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro- a cesos es el siguiente: 8 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 13 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 15. Proc A CPU (2ut.) E/S D1 (2ut.) CPU (3ut.) E/S D2 (5ut.) CPU (1ut) Proc B CPU (5ut.) E/S D1 (1ut.) CPU (1ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S e est´ n siendo utilizados. a 19. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. La interrupci´ n de reloj se produce cada 5 unidades de tiempo. o Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup- o ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento o de la interrupci´ n software consume 2 unidades de tiempo. o Existe un dispositivo de entrada/salida sobre el que se pueden realizar operaciones en paralelo con la CPU. Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de a o E/S (IH) - Nivel 1: Interrupci´ n de reloj (IR) o @ibaumo - Nivel 2 (menos prioritario): Interrupci´ n software (IS) o Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini- a cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro- a cesos es el siguiente: Proc A CPU (3ut.) E/S (3ut.) CPU (2ut.) E/S (1ut.) CPU (1ut.) Proc B CPU (8ut.) E/S (1ut.) CPU (1ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S e est´ n siendo utilizados. a 20. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. La interrupci´ n de reloj se produce cada 4 unidades de tiempo. o Las rutinas de tratamiento de las interrupciones hardware y de la inte- rrupci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamien- o to de la interrupci´ n software consume 2 unidades de tiempo. o Existen un dispositivo de entrada/salida sobre el que se pueden realizar operaciones en paralelo con la CPU. 9 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 14 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 16. Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de a o E/S (IH) - Nivel 1: Interrupci´ n de reloj (IR) o - Nivel 2 (menos prioritario): Interrupci´ n software (IS) o Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini- a cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro- a cesos es el siguiente: Proc A CPU (6ut.) E/S (1ut.) CPU (2ut.) Proc B CPU (2ut.) E/S (6ut.) CPU (3ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S e est´ n siendo utilizados. a 21. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. La interrupci´ n de reloj se produce cada 4 unidades de tiempo. o Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup- o @ibaumo ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento o de la interrupci´ n software consume 1 unidad de tiempo. o Existe un dispositivo de entrada/salida sobre el que se pueden realizar operaciones en paralelo con la CPU. Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de a o E/S (IH) - Nivel 1: Interrupci´ n de reloj (IR) o - Nivel 2 (menos prioritario): Interrupci´ n software (IS) o Existen tres procesos A, B y C que est´ n listos para ejecutar, y que, ini- a cialmente, ser´ n atendidos en ese orden. El modelo que siguen estos tres a procesos es el siguiente: Proc A CPU (3ut.) E/S (10ut.) CPU (4ut.) Proc B CPU (6ut.) Proc C CPU (3ut.) E/S (4ut.) CPU (1ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a tiempo teniendo en cuenta que cuando un proceso pasa de bloqueado a listo se sit´ a al principio de la cola de espera. Indica tambi´ n aquellos instantes u e en los que los dispositivos de E/S est´ n siendo utilizados. a 10 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 15 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 17. 22. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. La interrupci´ n de reloj se produce cada 4 unidades de tiempo. o Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup- o ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento o de la interrupci´ n software consume 2 unidades de tiempo. o Existe un dispositivo de entrada/salida sobre el que se pueden realizar operaciones en paralelo con la CPU. Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de a o E/S (IH) - Nivel 1: Interrupci´ n de reloj (IR) o - Nivel 2 (menos prioritario): Interrupci´ n software (IS) o Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini- a cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro- a cesos es el siguiente: Proc A CPU (3ut.) E/S (1ut.) CPU (1ut.) E/S (1ut.) CPU (1ut.) @ibaumo Proc B CPU (4ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S e est´ n siendo utilizados. a 23. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. La interrupci´ n de reloj se produce cada 4 unidades de tiempo. o Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup- o ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento o de la interrupci´ n software consume 1 unidad de tiempo. o Existe un dispositivo de entrada/salida sobre el que se pueden realizar operaciones en paralelo con la CPU. Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo de a o E/S (IH) - Nivel 1: Interrupci´ n de reloj (IR) o - Nivel 2 (menos prioritario): Interrupci´ n software (IS) o 11 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 16 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 18. Existen dos procesos A y B que est´ n listos para ejecutar, de modo que ini- a cialmente A ser´ atendido antes que B. El modelo que siguen estos dos pro- a cesos es el siguiente: Proc A CPU (14ut.) Proc B CPU (2ut.) E/S (1ut.) CPU (1ut.) E/S (1ut.) CPU (1ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S e est´ n siendo utilizados. a 24. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. La interrupci´ n de reloj se produce cada 4 unidades de tiempo. o Las rutinas de tratamiento de las interrupciones hardware y de la inte- rrupci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamien- o to de la interrupci´ n software consume 2 unidades de tiempo. o Existen dos dispositivos de entrada/salida sobre los que se pueden rea- lizar operaciones en paralelo. @ibaumo Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n hardware del dispositivo 1 a o (IH1) - Nivel 1: Interrupci´ n hardware del dispositivo 2 (IH2) o - Nivel 2: Interrupci´ n de reloj (IR) o - Nivel 3 (menos prioritario): Interrupci´ n software (IS) o Existen tres procesos A, B y C que est´ n listos para ejecutar en ese mismo a orden. El modelo que siguen estos dos procesos es el siguiente: Proc A CPU (1ut.) E/S D1 (8ut.) CPU (1ut.) Proc B CPU (2ut.) E/S D2 (2ut.) CPU (7ut.) Proc C CPU (4ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a tiempo teniendo en cuenta adem´ s que cuando los procesos pasan de blo- a queados a listos se sit´ an al principio de la cola de espera. Indica tambi´ n u e aquellos instantes en los que los dispositivos de E/S est´ n siendo utilizados. a 25. Considera un sistema con las siguientes caracter´sticas: ı Se utiliza el algoritmo de planificaci´ n Round-Robin con un quantum o de dos interrupciones de reloj. 12 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 17 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 19. La interrupci´ n de reloj se produce cada 5 unidades de tiempo. o Las rutinas de tratamiento de la interrupci´ n hardware y de la interrup- o ci´ n de reloj consumen 1 unidad de tiempo. La rutina de tratamiento o de la interrupci´ n software consume 1 unidad de tiempo. o Existe un dispositivo de entrada/salida sobre el que se pueden realizar operaciones en paralelo con la CPU. Los niveles de prioridad de las interrupciones son: - Nivel 0 (m´ s prioritario): Interrupci´ n de reloj (IR) a o - Nivel 1: Interrupci´ n hardware del dispositivo de E/S (IH) o - Nivel 2 (menos prioritario): Interrupci´ n software (IS) o Existen tres procesos A, B y C que est´ n listos para ejecutar en ese mismo a orden. El modelo que siguen estos tres procesos es el siguiente: Proc A CPU (15ut.) Proc B CPU (2ut.) E/S (1ut.) CPU (3ut.) Proc C CPU (1ut.) E/S (6ut.) CPU (4ut.) Indica qu´ proceso o interrupci´ n est´ atendiendo la CPU en cada unidad de e o a @ibaumo tiempo. Indica tambi´ n aquellos instantes en los que los dispositivos de E/S e est´ n siendo utilizados. a 1.3. Hilos 26. Modifica el programa que se ilustra en el enunciado del problema 15 de ma- nera que reciba dos n´ meros enteros como par´ metros de entrada y calcule u a sus factoriales de forma concurrente utilizando dos hilos que se ejecutan en paralelo con el hilo principal. El hilo principal deber´ esperar a que terminen a los otros dos hilos. Recuerda que para compilarlo se debe a˜ adir -lpthread a n la orden gcc. 27. Modifica el programa resultado del problema 26 de manera que no est´ li- e mitado a 2 el n´ mero de factoriales a calcular. Haz que se creen tantos hilos u como par´ metros de entrada y que todos se ejecuten de forma concurrente. a El hilo principal debe esperar a que terminen el resto de hilos y, a medida que vayan terminando, muestre un mensaje que indique un identificador del hilo finalizado. 28. Modifica el programa soluci´ n del problema 13 para que la escritura de ca- o da cadena la haga un hilo diferente que se ejecutan en paralelo con el hilo principal. El hilo principal debe esperar a que terminen los otros dos hilos. 13 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 18 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 20. 29. El siguiente programa cuenta el n´ mero de veces que el car´ cter ’a’ o ’A’ u a aparece en el fichero indicado como par´ metro de entrada. Modif´calo para a ı ´ que ahora se cree un hilo y sea este el que ejecute la funci´ n cuenta. o #include unistd.h #include stdlib.h #include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #define MAXLON 1000 void cuenta (char ∗nombre) { int pos, cont= 0, leidos; char cadena[MAXLON]; int fd; fd= open (nombre, O RDONLY); while ((leidos= read (mf, cadena, MAXLON))!= 0) for (pos= 0; pos leidos; pos++) if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’)) cont++; printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn, nombre, cont); close (fd); } int main (int argc, char ∗argv[]) { @ibaumo if (argc!= 2) { printf (Indica el nombre de un fichero.n); exit(0); } cuenta (argv[1]); return 0; } 30. Modifica el programa resultado del problema 29 para que se creen tantos hilos como ficheros especificados como par´ metros de entrada, y que todos a los hilos creados se ejecuten de forma concurrente. 31. Modifica el programa resultado del problema 30 para que el resultado de la b´ squeda lo informe el hilo principal cuando hayan terminado el resto de u hilos. Haz uso del paso de par´ metros a un hilo para que cada hilo pueda a devolver el resultado de la b´ squeda al hilo principal. u 32. Modifica el programa soluci´ n del problema 30 para obtener el n´ mero de o u espacios en blanco que hay en cada uno de los ficheros dados como par´ me- a tros. Inicialmente, se deben crear tantos procesos como ficheros especifica- dos. Cada proceso crear´ los hilos necesarios, que son los que realizar´ n la a a b´ squeda, atendiendo a la restricci´ n de que un hilo procesar´ como m´ xi- u o a a mo K caracteres, donde K es una constante predefinida. Todos los hilos y procesos se han de ejecutar de forma concurrente. Cada proceso esperar´ a a que terminen sus hilos y mostrar´ el total de espacios encontrados. a 14 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 19 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 21. Cap´tulo 2 ı Comunicaci´ n y Sincronizaci´ n o o de Procesos 2.1. Tuber´as ı ´ 33. Se desea informar del tiempo invertido en ejecutar las ordenes ls | wc -l. Para ello se escribe el siguiente programa. Sin embargo, no informa de forma correcta. Modif´calo para que lo haga sin cambiar el n´ mero de procesos ı u @ibaumo que se est´ n generando. a #include stdio.h #include stdlib.h #include unistd.h #include time.h #include sys/types.h #include sys/wait.h int main (int argc, char ∗argv[]){ int tubo[2]; time t ini, fin; pipe(tubo); if(fork()==0){ if(fork()==0){ dup2(tubo[1],STDOUT FILENO); close(tubo[0]); close(tubo[1]); execlp(ls,ls,NULL); }else{ dup2(tubo[0],STDIN FILENO); close(tubo[0]); close(tubo[1]); execlp(wc,wc,-l,NULL); } } else{ printf(Tiempo invertido: %ld segundosn, fin-ini); } return 0; } 15 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 20 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 22. 34. Observa el siguiente fragmento de c´ digo que trata de realizar lo mismo que o si un usuario escribiera ls | sort en la l´nea de comandos de un sistema UNIX. ı Indica qu´ problemas se producen, por qu´ y c´ mo resolverlos. e e o int tubo[2]; pipe(tubo); if (fork()!=0) { dup2(tubo[1], STDIN FILENO); execlp(sort, sort, NULL); close(tubo[0]); close(tubo[1]); } else { dup2(tubo[0], STDOUT FILENO); close(tubo[1]); close(tubo[0]); execlp(ls, ls, NULL); } 35. Al ejecutar el siguiente programa, el proceso no termina. Explica por qu´ . e Da una soluci´ n que no cambie el n´ mero de procesos que se generan. o u int main(int argc, char ∗argv[]) { int tubo[2]; pipe(tubo); if (fork()==0) { if (fork()== 0) { dup2 (tubo[1], STDOUT FILENO); close(tubo[0]); @ibaumo close(tubo[1]); execlp(ls, ls, NULL); } else { dup2 (tubo[0], STDIN FILENO); close(tubo[0]); close(tubo[1]); execlp(wc, wc, -l, NULL); } } else { wait(NULL); printf (Fin del proceson); } } 36. Describe todas las situaciones que se producen o podr´an producirse al eje- ı cutar el siguiente programa: int main (int argc,char ∗ argv[]) { int tubo[2]; FILE ∗fichero; char linea[MAX]; pipe(tubo); if(!(fichero=fopen(argv[1],r))){ printf(Error al abrir el fichero %sn,argv[1]); exit(2); } 16 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 21 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 23. while(fgets(linea,MAX,fichero)) write(tubo[1],linea,strlen(linea)); fclose(fichero); close (tubo[1]); dup2 (tubo[0],STDIN FILENO); close (tubo[0]); execlp(sort,sort,NULL); exit(0); } 37. Describe todas las situaciones que se producen o podr´an producirse al eje- ı cutar el siguiente programa: int main(int argc, char ∗argv[]) { int tubo[2]; pipe(tubo); if (fork()==0) { close(tubo[0]); dup2(tubo[1], STDOUT FILENO); close(tubo[1]); execlp(ls, ls, NULL); } else { dup2(tubo[0], STDIN FILENO); close(tubo[0]); close(tubo[1]); wait(NULL); execlp(wc, wc, -l, NULL); @ibaumo } exit(0); } ´ 38. Escribe un programa que ejecute la siguiente l´nea de ordenes igual que lo ı har´a un int´ rprete de comandos: paste fich1 fich2 | sort | nl fich3. Debes ı e considerar que fich1, fich2 y fich3 ser´ n par´ metros dados a tu programa en a a la l´nea de comandos. ı 39. Escribe un programa que genere tres procesos en paralelo que colaboran para realizar las siguientes tareas: El primer proceso, utilizando la orden grep, encontrar´ las l´neas de un a ı fichero (fich1) que contienen una palabra (ambos dados como par´ me- a tros en la l´nea de comandos) y las escribir´ en una tuber´a. ı a ı El segundo proceso, utilizando la orden grep, encontrar´ las l´neas de a ı un fichero (fich2) que contienen la misma palabra (ambos dados como par´ metros en la l´nea de comandos) y las escribir´ en la misma tuber´a. a ı a ı El tercer proceso, utilizando la orden wc, leer´ de la tuber´a las l´neas a ı ı producidas por los otros dos, las contar´ y escribir´ el resultado en un a a nuevo fichero (fich3) pasado como par´ metro en la l´nea de comandos. a ı As´, el programa se utilizar´ en la l´nea de comandos de la siguiente forma: ı a ı 17 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 22 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 24. $ programa palabra fich1 fich2 fich3. La figura 2.1 muestra gr´ ficamente la a comunicaci´ n requerida entre los procesos. o Figura 2.1: Esquema de funcionamiento. 40. Escribe un programa que genere tres procesos en paralelo que colaboran para realizar las siguientes tareas: El primer proceso leer´ l´neas de un fichero de texto dado como par´ me- a ı a tro y escribir´ alternativamente en dos tuber´as las l´neas pares e impa- a ı ı res del mismo. El segundo proceso, utilizando la orden grep, leer´ de la tuber´a que a ı contiene las l´neas pares y seleccionar´ aquellas l´neas que contengan ı a ı una palabra dada como par´ metro en la l´nea de comandos. El resultado a ı se almacenara en un fichero cuyo nombre estar´ formado por la palabra a dada seguido de .txt. @ibaumo El tercer proceso realiza una funci´ n similar sobre la tuber´a que con- o ı tiene las l´neas impares, pero utilizando otra palabra tambi´ n dada co- ı e mo par´ metro. a La figura 2.2 muestra gr´ ficamente los procesos y c´ mo se comunican estos a o cuando el programa se ejecuta con los siguientes par´ metros: $ programa a fichero.txt uno dos Figura 2.2: Esquema de funcionamiento. 41. Escribe un programa que genere los procesos necesarios para que colaboren en realizar las siguientes tareas: Tarea 1: leer l´neas de un fichero de texto dado como par´ metro de ı a entrada y escribir alternativamente en dos tuber´as (tuber´a 1 y tuber´a ı ı ı 2) las l´neas pares e impares del mismo. ı 18 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 23 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 25. Tarea 2: utilizando el comando grep, leer de la tuber´a que contiene las ı l´neas pares y seleccionar aquellas l´neas que contengan una palabra ı ı dada como par´ metro en la l´nea de comandos. El resultado se enviar´ a a ı a trav´ s de la tuber´a 3. e ı Tarea 3: realizar una funci´ n similar a la tarea 2 pero sobre la tuber´a o ı que contiene las l´neas impares y utilizando otra palabra diferente tam- ı bi´ n dada como par´ metro de entrada. e a Tarea 4: ejecutar el comando sort sobre la informaci´ n que se recoja o por la tuber´a 3 de manera que se muestren de forma ordenada las l´neas ı ı recogidas. Observa la siguiente figura 2.3. En ella se representa de forma gr´ fica una a propuesta de los procesos que se deben generar y de c´ mo se comunican es- o tos cuando el programa se ejecute con los siguientes par´ metros: $ programa a fichero.txt uno dos. Antes de comenzar a escribir la soluci´ n, determina si o est´ s de acuerdo o no con el esquema de funcionamiento propuesto. Si no lo a est´ s explica porqu´ . a e @ibaumo Figura 2.3: Esquema de funcionamiento. 2.2. Sem´ foros a 42. Dados los siguientes procesos y sus respectivas secuencias de c´ digo, indica o si existir´a o no situaci´ n de interbloqueo y explica por qu´ . En cualquier ı o e caso, indica tambi´ n la salida por pantalla y el valor final de los sem´ foros. e a Sup´ n que inicialmente todos los sem´ foros tienen valor cero. o a Proceso 1 Proceso 2 Proceso 3 --------- --------- --------- printf(3); sem_wait(s1); sem_wait(s2); sem_post(s3); printf(1); sem_wait(s4); printf(4); sem_wait(s3); printf(2); sem_post(s2); sem_post(s4); printf(5); sem_post(s1); sem_wait(s3); sem_post(s3); 19 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 24 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 26. 43. Considera que los siguientes fragmentos de c´ digo se ejecutan en paralelo: o C´digo A: o C´digo B: o --------- --------- printf(A1); printf(B1); sem_post(s1); sem_wait(s1); sem_wait(s2); printf(B2); printf(A2); sem_post(s3); sem_wait(s2); sem_wait(s3); sem_post(s1); printf(B3); printf(A3); sem_post(s2); sem_wait(s1); sem_post(s2); printf(B4); Sabiendo que todos los sem´ foros est´ n inicializados a 0, indica todas las a a posibles salidas que puede proporcionar su ejecuci´ n y si se produce o no o interbloqueo para cada una de ellas. 44. Modifica el programa resultado del problema 31 para que, utilizando una variable global a la cual acceden todos los hilos (ll´ mala cuenta blancos), a estos acumulen el total de blancos encontrados. Utiliza un sem´ foro para a asegurar que los accesos a dicha variable se realizan de forma adecuada. Haz que el programa principal informe tambi´ n del resultado. e 45. Escribe un programa que ejecute tres hilos en paralelo a los que llamaremos @ibaumo A, B y C. El hilo A consta de tres bloques de c´ digo (a1, a2 y a3), el hilo B o de otros cuatro (b1, b2, b3 y b4) y el C de 3 (c1, c2 y c3). Haz que el c´ digo o de cada uno de estos bloques consista en repetir cinco veces los siguientes pasos: escribir un mensaje que lo identifique y realizar un retardo aleatorio. Ejecuta el programa para comprobar que los hilos A, B y C se ejecutan en paralelo y que sus bloques de c´ digo pueden alternarse de varias formas o distintas. Ahora, modifica el programa anterior para que los tres hilos se sincronicen de la siguiente forma: c1 no debe comenzar hasta que acabe a1 a2 no debe comenzar hasta que acabe b1 c2 no debe comenzar hasta que acabe b2 b3 no debe comenzar hasta que acabe a2 a3 no debe comenzar hasta que acabe c2 ´ b4 debe acabar el ultimo 46. Se crean tres hilos de manera que uno ejecuta escribirA, otro escribirB y el tercero escribirC. Introduce los sem´ foros oportunos para que la salida sea a ABCABCABCABCABCABC. #include stdio.h #include stdlib.h #include time.h 20 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 25 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 27. #include unistd.h #include pthread.h #define MAX 6 void ∗escribirA (void ∗nada){ int num; for(num=0;numMAX;num++){ printf(A); fflush(NULL); sleep(random() %3); } pthread exit(NULL); } void ∗escribirB (void ∗nada){ int num; for(num=0;numMAX;num++){ printf(B); fflush(NULL); sleep(random() %2); } pthread exit(NULL); } void ∗escribirC (void ∗nada){ int num; for(num=0;numMAX;num++){ printf(C); fflush(NULL); @ibaumo sleep(random() %2); } pthread exit(NULL); } int main (int argc, char ∗argv[]) { pthread t th1, th2, th3; srandom(time(NULL)); pthread create(th1, NULL, escribirA, NULL); pthread create(th2, NULL, escribirB, NULL); pthread create(th3, NULL, escribirC, NULL); pthread join(th1, NULL); pthread join(th2, NULL); pthread join(th3, NULL); return 0; } 47. Observa el siguiente fragmento de c´ digo donde los sem´ foros sem1 y sem2 o a est´ n inicializados a cero, un hilo ejecuta la funci´ n incrementa y otro la a o funci´ n decrementa. Describe los valores que, durante la ejecuci´ n, puede o o adoptar la variable num as´ como las posibles situaciones de interbloqueo ı que pudieran darse. 21 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 26 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 28. int num=10; void ∗ incrementa(void ∗nada) { int i; for (i=0;i3;i++){ sem wait(sem1); num++; printf(Inc. N´ mero = %dn,num); u sem post(sem1); } sem post(sem2); sleep(random() %3); sem wait(sem2); pthread exit(NULL); } void ∗ decrementa(void ∗nada){ int i; for (i=0;i3;i++){ sem post(sem1); sleep(random() %3); sem wait(sem2); num--; printf(Dec. N´ mero = %dn,num); u sem post(sem2); sem wait(sem1); } sem wait(sem1); pthread exit(NULL); } @ibaumo 48. Se crean dos hilos de manera que uno ejecuta escribirA y el otro escribirB. Introduce los sem´ foros oportunos para que la salida sea BABABABABA. a No olvides indicar los valores iniciales de los sem´ foros que utilices. a void ∗escribirA (void ∗p) { int i; for (i= 0; i 5; i++) { printf (A); fflush(NULL); sleep(random() %2); } pthread exit(NULL); } void ∗escribirB (void ∗p) { int i; for (i= 0;i 5; i++) { printf (B); fflush(NULL); sleep(random() %2); } pthread exit(NULL); } 49. Dado el siguiente c´ digo indica si existe o no interbloqueo. En el caso de o existir, indica claramente para cada hilo en qu´ l´nea de c´ digo se queda e ı o bloqueado y en qu´ iteraci´ n del bucle ocurre (valores de las variables i, j, e o k). Observa los valores de inicializaci´ n de los sem´ foros. o a 22 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 27 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 29. sem t s1, s2, s3; void ∗escribirA (void ∗p){ int i; srandom (pthread self ()); for (i= 0; i MAX; i++){ printf (A); sem post (s2); sem wait (s1); fflush (NULL); sleep (random() %3); } pthread exit (NULL); } void ∗escribirB (void ∗p){ int j; srandom (pthread self ()); for (j= 0; j MAX; j++){ sem wait (s2); printf (B); sem post (s3); sem wait (s2); fflush (NULL); sleep (random() %2); } pthread exit (NULL); } void ∗escribirC (void ∗p){ @ibaumo int k; srandom (pthread self ()); for (k= 0; k MAX; k++){ sem wait (s3); printf (C); sem post (s1); sem wait (s3); fflush (NULL); sleep (random() %2); } pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t th1, th2, th3; sem init (s1, 0, 1); sem init (s2, 0, 1); sem init (s3, 0, 0); pthread create (th1, NULL, escribirA, NULL); pthread create (th2, NULL, escribirB, NULL); pthread create (th3, NULL, escribirC, NULL); pthread join (th1, NULL); pthread join (th2, NULL); pthread join (th3, NULL); return 0; } 50. Considera el siguiente trozo de c´ digo del problema productor-consumidor: o #include stdio.h #include stdlib.h #include semaphore.h 23 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 28 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 30. #include pthread.h #include unistd.h #include stdbool.h #define MAX 10 #define FIN -1 int buffer[MAX]; sem t huecos, elementos; int generar dato (void) { return random() %256;} int numero aleatorio(void) { return random() %100;} void ∗productor (void ∗p) { int pos productor= 0; int num, dato, n; n= numero aleatorio(); printf (Productor con %d datosn, n); for(num= 0; num n; num++) { dato= generar dato(); sem wait (huecos); buffer[pos productor]= dato; pos productor= (pos productor+ 1) %MAX; sem post (elementos); } buffer[pos productor]= FIN; pthread exit (NULL); } @ibaumo void ∗consumidor(void ∗p){ int pos consumidor, dato; bool continuar= true; while (continuar) { sem wait (elementos); dato= buffer[pos consumidor]; pos consumidor= (pos consumidor+1) %MAX; if (dato== FIN) continuar= false; sem post (huecos); printf (Numero aleatorio: %dn, dato); } pthread exit (NULL); } Este c´ digo contiene errores y est´ incompleto. Corrige y completa. Haz que o a el hilo consumidor muestre en pantalla todos los datos producidos por el hilo productor. 51. Realiza las modificaciones oportunas al c´ digo resultado del problema 50 o para que en lugar de un hilo productor hayan tres que se ejecuten en parale- lo. El consumidor terminar´ cuando haya consumido todos los datos produ- a cidos. 52. Escribe un programa que ejecute dos hilos en paralelo para realizar las si- guientes tareas: 24 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 29 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 31. El primer hilo calcular´ los n´ meros primos que hay entre dos n´ meros a u u que el programa recibe como par´ metros. Para enviar estos datos al a segundo hilo, los almacenar´ en un buffer intermedio de 5 elementos a de capacidad. El segundo hilo tomar´ los datos que aparezcan en el buffer intermedio a y calcular´ la suma de los d´gitos de cada n´ mero. Para cada n´ mero a ı u u primo se mostrar´ en la salida est´ ndar una l´nea que contendr´ dicho a a ı a n´ mero y la suma de sus d´gitos. u ı Deber´ s utilizar sem´ foros para que los dos hilos se sincronicen en el acceso a a al buffer intermedio. Estas son las funciones para comprobar si un n´ mero u es primo y para calcular la suma de los d´gitos de un n´ mero. ı u /∗ Devuelve la suma de los d´gitos del n´mero dado ∗/ ı u int suma digitos (int numero) { int suma= 0; while (numero 0) { suma+= numero %10; numero/= 10; } return suma; } @ibaumo /∗ Indica si el n´mero dado es primo ∗/ u bool es primo (int numero) { int divisor; for (divisor= 2; divisor= sqrt(numero); divisor++) if (numero %divisor== 0) return false; return true; } 53. Escribe un programa que realice una simulaci´ n de la evoluci´ n del estado o o de las reservas en una aula de libre acceso. Para simplificar, sup´ n que el aula o tiene s´ lo un ordenador que se puede reservar en per´odos de 1 hora, desde o ı las 9:00 hasta las 21:00. 25 alumnos pueden reservar per´odos individuales ı de 1 hora, cancelar reservas y consultar el estado de las reservas. La simulaci´ n debe consistir en que cada alumno realice cuatro operacio- o nes, cada una de las cuales podr´ ser una reserva, cancelaci´ n o consulta. La a o elecci´ n de la operaci´ n ser´ aleatoria, pero con mayor probabilidad para la o o a realizaci´ n de reservas (50 %) que para la realizaci´ n de consultas y cancela- o o ciones (25 % cada una). Cuando la operaci´ n a realizar sea una reserva, debe o elegirse aleatoriamente la hora que el alumno va a reservar. El programa debe implementar un hilo principal que lanza 25 hilos en parale- lo, uno por cada alumno. Mediante el empleo de sem´ foros debe garantizarse a 25 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 30 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 32. que los accesos a la tabla de reservas sean correctos. En concreto, cuando se realice una reserva o cancelaci´ n no puede realizarse ninguna otra operaci´ n o o en paralelo sobre la tabla, pero una consulta puede simultanear su acceso a la tabla con otras consultas. En la implementaci´ n de la consulta de la tabla, muestra por pantalla el esta- o do de cada per´odo de una hora en una l´nea distinta. Para realizar una reser- ı ı va, comprueba que el per´odo que se solicita reservar est´ libre. Al realizar ı e una cancelaci´ n, deben quedar libres todas las horas que tuviese reservadas o el estudiante que la solicita. Si ese estudiante no tuviese ninguna reserva se debe mostrar un mensaje de error. Como todas las operaciones est´ n controladas por sem´ foros, escribe mensa- a a jes que indiquen el estado de las operaciones diferenciando cu´ ndo se solicita a realizar una acci´ n (a´ n no se tiene autorizaci´ n), y cu´ ndo se realiza efec- o u o a tivamente (ya se tiene autorizaci´ n). As´, se puede seguir la evoluci´ n de las o ı o operaciones y los efectos que producen en el estado de la tabla de reservas. A continuaci´ n tienes un ejemplo del tipo de traza que se espera obtener. o Solicitud de reserva de al012: 9-10 Reserva de al012: 9-10 Solicitud de consulta de al004 Solicitud de cancelaci´n de al006 o @ibaumo Solicitud de reserva de al000: 15-16 Solicitud de consulta de al019 Consulta de al019: 9-10 = al012 Consulta de al019: 10-11 = LIBRE Consulta de al019: 11-12 = LIBRE Consulta de al019: 12-13 = LIBRE Consulta de al019: 13-14 = LIBRE Consulta de al019: 14-15 = LIBRE Consulta de al019: 15-16 = LIBRE Consulta de al019: 16-17 = LIBRE Consulta de al019: 17-18 = LIBRE Consulta de al004: 9-10 = al012 Consulta de al004: 10-11 = LIBRE Consulta de al004: 11-12 = LIBRE Consulta de al004: 12-13 = LIBRE Consulta de al004: 13-14 = LIBRE Consulta de al004: 14-15 = LIBRE Consulta de al004: 15-16 = LIBRE Consulta de al004: 16-17 = LIBRE Consulta de al004: 17-18 = LIBRE Consulta de al004: 18-19 = LIBRE Consulta de al004: 19-20 = LIBRE Consulta de al004: 20-21 = LIBRE Consulta de al019: 18-19 = LIBRE Consulta de al019: 19-20 = LIBRE Consulta de al019: 20-21 = LIBRE Denegada cancelaci´n de al006: No tiene reservas o Reserva de al000: 15-16 26 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 31 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 33. Solicitud de reserva de al010: 9-10 Denegada reserva de al010: 9-10 est´ ocupada a Solicitud de cancelaci´n de al012 o Cancelaci´n de al012: 9-10 o ... o ı ´ 54. Un puente es estrecho y s´ lo permite pasar veh´culos en un unico sentido al mismo tiempo. Si pasa un coche en un sentido y hay coches en el mismo sentido que quieren pasar, entonces estos tienen prioridad frente a los del otro sentido (si hubiera alguno esperando para entrar en el puente). No hay l´mite ı al n´ mero de veh´culos que pueden haber en el puente al mismo tiempo. u ı Simula el sistema suponiendo que los coches son hilos y el puente el recurso compartido. Utiliza sem´ foros para garantizar que se cumplen las condicio- a nes de acceso al puente. Cada hilo debe mostrar por pantalla cu´ ndo entra a en el puente y cu´ ndo lo abandona.Se generar´ n un total de 100 veh´culos, a a ı 50 en un sentido y 50 en el otro. Tras un tiempo de espera al azar (utili- zar sleep(random() %20) o algo similar) los veh´culos intentan entrar en el ı ´ puente y, si lo consiguen, permanecer´ n en el durante un segundo (sleep(1)) a antes de abandonarlo. Se apreciar´ m´ s el comportamiento del sistema si se a a alterna la creaci´ n de hilos en un sentido u otro. o @ibaumo 27 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 32 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 34. Cap´tulo 3 ı Gesti´ n de Archivos y Directorios o 3.1. Sistemas de Archivos 55. Disponemos de un disco duro de 20 GB de capacidad. Hay establecida sobre ´ ´ el una unica partici´ n que contiene un sistema de ficheros del tipo FAT32 en o el que cada agrupamiento (cluster) consta de 16 sectores de 512 bytes cada uno. ¿Cu´ ntos sectores del disco se necesitar´ n para almacenar cada copia a a de la FAT? Razona tu respuesta. @ibaumo 56. La polic´a ha arrestado al sospechoso de un delito. Al analizar el contenido ı de su ordenador piensan que pueden inculparle pues el contenido del mismo es el siguiente: N´ m de bloque de datos u Contenido 10 he 11 sido 12 yo 13 no 14 sigan 15 buscando Como experto inform´ tico, pides consultar el contenido de la FAT, que es el a siguiente: N´ m de entrada en la FAT u Contenido 10 11 11 EOF 12 13 13 10 14 15 15 12 ¿Apoyar´as la opini´ n de la polic´a? Razona tu respuesta. ı o ı 29 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 33 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 35. 57. Tenemos un sistema de ficheros tipo FAT sobre el que hay almacenado un fichero de 160 Kbytes. Sabemos que para dicho fichero se emplean 10 en- tradas de la FAT y que cada sector del disco contiene 512 bytes. ¿Cu´ ntos a sectores como m´nimo forman cada bloque o agrupamiento en dicho siste- ı ma? Razona tu respuesta. 58. Se dispone de una partici´ n de disco con sistema de ficheros basado en o FAT16. Si el tama˜ o de bloque es de 1KB, ¿cu´ ntos KB de dicha partici´ n n a o podr´ n direccionarse como m´ ximo? Si la partici´ n resulta tener un tama˜ o a a o n de 2GB, ¿qu´ tama˜ o deber´a como m´nimo tener el bloque para poder di- e n ı ı reccionar la partici´ n por completo? o 59. Se dispone de una partici´ n de disco con sistema de ficheros basado en o FAT16. A la hora de ponerle formato el usuario especifica que los bloques sean de tama˜ o 4Kbytes ¿Cu´ ntos Kbytes te´ ricamente podr´ n direccionar- n a o a se como m´ ximo? Si la partici´ n resulta tener un tama˜ o de 8Gbytes, ¿con- a o n sideras adecuado el tama˜ o de bloque escogido por el usuario? Justifica la n respuesta. En caso de que no est´ s de acuerdo prop´ n un tama˜ o de bloque e o n e indica en cu´ ntos de esos bloques se almacena la FAT. a 60. Para una partici´ n de 8GB y tama˜ o de bloque de 1 KB, o n @ibaumo Si se utiliza un sistema de ficheros basado en FAT16, ¿qu´ cantidad de e espacio en disco queda inutilizable? Si se utiliza un sistema de ficheros basado en nodos-i, donde cada nodo- i consta de dos ´ndices directos, dos indirectos simples y dos indirectos ı dobles, y para referenciar un bloque se utilizan 128 bits, ¿qu´ cantidad e de datos de un fichero que en concreto ocupa 131 KB puede ser irrecu- perable en el caso de que un bloque de la partici´ n resultara ilegible? o Analiza todos los casos posibles. 61. Considera un sistema de ficheros basado en nodos-i, en el que cada nodo-i contiene cinco ´ndices directos, tres indirectos simples, dos indirectos dobles ı y uno indirecto triple. Si el tama˜ o de un bloque de datos es de 2 Kbytes y n para referenciar a un bloque se utilizan 64 bits, ¿cu´ ntos bloques de disco a almacenar´ n enlaces para un fichero que contiene 1548 Kbytes de datos? a Razona tu respuesta. 62. Sea una partici´ n de disco donde el tama˜ o de bloque es de 4KB. Se utiliza o n un sistema de ficheros basado en nodos-i, donde cada nodo-i consta de dos ´ndices directos, dos indirectos simples y uno indirecto doble. Si para refe- ı renciar a un bloque se utilizan 32 bits, ¿cu´ l es el n´ mero de bloques que a u contendr´ n enlaces si el fichero ocupa el m´ ximo tama˜ o posible? a a n 30 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 34 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 36. 3.2. Archivos y Directorios 63. La siguiente funci´ n muestra el nombre de todas las entradas del directorio o que se le pasa como par´ metro: a void listado(char nomdir[]) { DIR ∗d; struct dirent ∗entrada; char ∗ruta; d= opendir(nomdir); if (d== NULL) printf(Error al abrir el directorion); else { entrada= readdir(d); while (entrada!= NULL) { ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2); sprintf(ruta, %s/ %s, nomdir, entrada-d name); printf( %sn, ruta); free(ruta); entrada= readdir(d); } closedir(d); } } ´ Modif´cala para que unicamente muestre aquellas entradas que se correspon- ı dan con enlaces simb´ licos a directorios. o @ibaumo 64. La siguiente funci´ n muestra el nombre de todas las entradas del directorio o que se le pasa como par´ metro: a void listado(char nomdir[]) { DIR ∗d; struct dirent ∗entrada; char ∗ruta; d= opendir(nomdir); if (d== NULL) printf(Error al abrir el directorion); else { entrada= readdir(d); while (entrada!= NULL) { ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2); sprintf(ruta, %s/ %s, nomdir, entrada-d name); printf( %sn, ruta); free(ruta); entrada= readdir(d); } closedir(d); } } Modif´cala para que por cada fichero regular que haya en el directorio se ı cree un archivo zip en el directorio /tmp y se muestre la diferencia de espacio entre el archivo original y el nuevo archivo zip. Crea el archivo zip con la orden zip ruta.zip ruta. 31 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 35 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 37. 65. Escribe un programa que dado un directorio como argumento de entrada elimine los ficheros, enlaces y directorios (s´ lo los vac´os) que hubiesen en o ı ´ el. El programa debe informar de si el directorio dado como par´ metro existe a as´ como de cada uno de los elementos eliminados. No hagas un recorrido ı ´ recursivo del arbol de directorios. 66. Escribe un programa que borre una serie de nombres de ficheros y/o direc- torios recibidos como par´ metros. Adem´ s, el programa debe mostrar para a a cada par´ metro dado: a si se trata de un fichero regular, un enlace simb´ lico, un directorio, o o bien si el nombre dado no es v´ lido a si dicho nombre pudo borrarse correctamente, as´ como el n´ mero de ı u bloques de disco que ser´ n liberados en tal caso. Ten en cuenta que, en a el caso de ficheros regulares, los bloques de disco s´ lo ser´ n liberados o a ´ si se trata del ultimo enlace f´sico sobre el fichero. ı 67. Escribe un programa que, a partir de un directorio dado como par´ metro, a informe de los ficheros regulares que encuentre a partir de dicho directorio ´ (deber´ recorrer el arbol de directorios a partir de dicho directorio) tales a que pertenezcan al usuario que ejecuta el programa, y se hayan accedido desde una hora antes del comienzo de la ejecuci´ n del programa. Durante el o @ibaumo recorrido recursivo del directorio dado, se deben ignorar aquellos directorios que no puedan ser abiertos por no tener los permisos necesarios. 68. Escribe un programa que calcule la suma de los bytes ocupados por todos los ficheros y directorios que est´ n contenidos a partir de un directorio dado e como par´ metro. ¿Qu´ ocurre cuando hay dos enlaces duros que hacen refe- a e rencia al mismo fichero? Haz que en estos casos el espacio ocupado se con- sidere s´ lo una vez. Ten en cuenta que la estructura stat contiene el n´ mero o u de nodo-i asignado al fichero. 69. Escribe un programa que reciba como argumentos un fichero regular y un di- rectorio, y cambie por enlaces simb´ licos al fichero regular todos los enlaces o ´ duros referidos a el que encuentre a partir del directorio dado. Para simpli- ficar, considera que tanto el fichero como el directorio se pasan al programa como caminos absolutos que no contienen el nombre ., ni el nombre .., ni ning´ n enlace simb´ lico. u o 70. Un reproductor multimedia recorre de forma recursiva el directorio /media (y sus subdirectorios) a la b´ squeda de ficheros con extensi´ n jpeg, avi y u o mp3. En la ruta /resultado hay tres carpetas de nombres jpeg, avi y mp3. Por cada fichero regular que encuentra con la extensi´ n adecuada en el proceso o de b´ squeda, crea un enlace simb´ lico en la carpeta correspondiente a la ex- u o tensi´ n del archivo. Por ejemplo, si encuentra un fichero con extensi´ n avi o o 32 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 36 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 38. crea el enlace simb´ lico a dicho fichero en el directorio /resultado/avi. Es- o cribe un programa en C que funcione de acuerdo al enunciado del problema. ´ Adem´ s, haz que no haya que crear el enlace al archivo si este ya existe. a @ibaumo 33 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 37 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 39. Cap´tulo 4 ı Gesti´ n de Memoria o 4.1. Paginaci´ n o 71. Considera un sistema de paginaci´ n en el que se puede direccionar como o m´ ximo 1 Gbyte de memoria, el tama˜ o de p´ gina es de 16 Kbytes y cada a n a byte se direcciona independientemente ¿Cu´ ntas p´ ginas podr´ tener asig- a a a nadas como m´ ximo un proceso en este sistema? Si empleamos una tabla a de p´ ginas con dos niveles, en el que la tabla de primer nivel contiene 1024 a @ibaumo entradas, ¿cu´ ntas tablas de segundo nivel son necesarias para un proceso a que requiere 6401 p´ ginas? Razona tu respuesta. a 72. Considera un sistema de paginaci´ n en el que las direcciones l´ gicas son o o de 22 bits y el tama˜ o de p´ gina es de 2 Kbytes. Sabiendo que cada by- n a te se direcciona independientemente, calcula el ahorro de memoria que ob- tendr´amos para representar la tabla de p´ ginas de un proceso que est´ utili- ı a a zando 90 Kbytes de memoria, cuando empleamos una tabla de p´ ginas con a dos niveles en lugar de tener una tabla de un solo nivel. En el sistema con dos niveles, debes considerar que se emplean 5 bits de la direcci´ n para el o segundo nivel. Adem´ s, cada entrada de las tablas de p´ ginas precisa 8 bytes. a a Razona la respuesta. 73. Considera un sistema de paginaci´ n en el que las direcciones l´ gicas son de o o 20 bits y el tama˜ o de p´ gina de 4 Kbytes. Sabiendo que cada byte se direc- n a ciona independientemente, calcula el ahorro de memoria que obtendr´amos ı para representar la tabla de p´ ginas de un proceso que est´ utilizando 192 a a Kbytes de memoria, cuando empleamos un tabla de p´ ginas con dos niveles a en lugar de tener una tabla de un solo nivel. En el sistema con dos niveles debes considerar que se emplea el mismo n´ mero de bits de la direcci´ n para u o cada nivel. Cada entrada de las tablas de p´ ginas precisa 16 bytes. Razona tu a respuesta. 74. Considera un sistema de paginaci´ n en el que las direcciones l´ gicas son de o o 22 bits y el tama˜ o de p´ gina de 2 Kbytes, y que cada byte se direcciona in- n a 35 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 38 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 40. dependientemente ¿Cu´ ntas p´ ginas podr´ tener asignadas como m´ ximo un a a a a proceso en este sistema? Si empleamos una tabla de p´ ginas de dos niveles, a ´ en la que la tabla de primer nivel contiene unicamente 8 entradas, ¿cu´ ntas a tablas de segundo nivel son necesarias para un proceso que requiere 1000 p´ ginas? Razona la respuesta. a 75. Lee las siguientes afirmaciones y razona si est´ s de acuerdo o no. Pon un a ejemplo que apoye tu respuesta. En un sistema de paginaci´ n, utilizar una tabla de p´ ginas de dos nive- o a les suele producir un ahorro en el consumo de memoria en comparaci´ n o con el uso de una tabla de p´ ginas de un nivel. a En un sistema de paginaci´ n, el n´ mero de p´ ginas que como m´ ximo o u a a se le puede asignar a un proceso es mayor en el caso de utilizar una ´ tabla de p´ ginas de dos niveles que en el caso de utilizar una unica a tabla de p´ ginas. a 76. Considera un sistema de paginaci´ n en donde se puede puede direccionar o un m´ ximo de 1GB y el tama˜ o de p´ gina es de 32KB. Sabiendo que cada a n a palabra de 16 bits se direcciona independientemente, calcula el ahorro de memoria que obtendriamos de representar la tabla de p´ ginas de un proce- a so que est´ utilizando 90MB de memoria, cuando empleamos una tabla de a @ibaumo p´ ginas de dos niveles en lugar de tener una tabla de un solo nivel. En el a sistema de dos niveles, debes considerar que se emplear´ el mismo n´ mero a u de bits para cada nivel. Adem´ s, cada entrada en la tabla de p´ ginas precisa a a de 16 bytes. Razona la respuesta. 77. Se considera un sistema de paginaci´ n en donde se puede direccionar un o m´ ximo de 1GB y el tama˜ o de p´ gina es de 32KB. Sabiendo que el tama˜ o a n a n de la palabra es de 64 bits y que cada palabra se direcciona independiente- mente, calcula el ahorro de memoria que obtendr´amos de representar la ta- ı bla de p´ ginas de un proceso que est´ utilizando 256 MB de memoria cuando a a se emplea una tabla de p´ ginas de dos niveles en lugar de tener una tabla de a un solo nivel. En el de dos niveles, debes considerar que se emplear´ el mis- a mo n´ mero de bits para cada nivel. Adem´ s cada entrada de p´ ginas precisa u a a de 8 bytes. Razona la respuesta. 4.2. Pol´ticas de Reemplazo ı Para realizar los siguientes ejercicios ten en cuenta que: Inicialmente los marcos est´ n libres. a La pol´tica de reemplazo s´ lo se utiliza a partir del momento en que no hayan ı o marcos libres. 36 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 39 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 41. 78. Considera un sistema de paginaci´ n bajo demanda en el que un proceso que o tiene asignados 3 marcos de p´ gina genera la siguiente secuencia de referen- a cias a p´ ginas: a 2,3,1,2,4,5,2,3,1,5,6,1 Indica qu´ accesos producir´an un fallo de p´ gina cuando se utilizan las e ı a pol´ticas de reemplazo local FIFO y LRU. Sabemos que este proceso se va a ı ejecutar muy a menudo en el sistema y nos interesa tener el mejor sistema de ´ paginaci´ n para el. ¿Valdr´a la pena aumentar el n´ mero de marcos de p´ gi- o ı u a na asignados al proceso hasta 4 para alguna de estas dos pol´ticas? Indica el ı n´ mero de fallos de p´ gina que se producir´an en esta nueva situaci´ n para u a ı o cada algoritmo. 79. Considera un sistema de paginaci´ n bajo demanda en el que un proceso que o tiene asignados 4 marcos de p´ gina genera la siguiente secuencia de referen- a cias a p´ ginas: a 4,2,4,1,6,3,2,5,6,4,1,3,5,3 Indica qu´ accesos producir´an un fallo de p´ gina cuando se utiliza cada una e ı a ´ de las pol´ticas de reemplazo local FIFO, LRU y optima. ı 80. Se ha de dise˜ ar un sistema de paginaci´ n bajo demanda en el que se utiliza n o una pol´tica de reemplazo local con tres marcos de p´ gina asignados para ı a @ibaumo cada proceso. Para la siguiente secuencia de referencias a p´ ginas: 1, 2, 3, a 2, 1, 5, 6, 3, 2, 1 ¿qu´ pol´tica de reemplazo producir´a un resultado m´ s e ı ı a ´ cercano a la optima, FIFO o LRU? Demu´ stralo indicando los accesos que e producir´an fallo de p´ gina para cada uno de los m´ todos. ı a e 37 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 40 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 42. Cap´tulo 5 ı Ejercicios Generales 81. Escribe un programa para limpiar el directorio /tmp. Recorriendo todos los subdirectorios que se encuentren a partir de /tmp, el programa debe eliminar todos los ficheros (de cualquier tipo) que pertenezcan al usuario que ejecuta el programa para los que haga m´ s de 2 semanas que no se acceden. En el a caso concreto de los directorios, se deben eliminar los que ya estaban vac´os ı o queden vac´os al eliminar los ficheros que conten´an, independientemente ı ı ´ del tiempo transcurrido desde su ultimo acceso. Adem´ s, debe identificar a @ibaumo los ficheros para los que haga m´ s de 1 semana pero menos de 2 que no se a acceden e informar al usuario de que ser´ n borrados pr´ ximamente. a o El programa recibir´ como par´ metro una direcci´ n de correo electr´ nico a a a o o la que enviar´ dos mensajes. El primer mensaje indicar´ en el asunto Fiche- a a ros borrados de /tmp y contendr´ el nombre de cada fichero o directorio que a se haya eliminado. El segundo mensaje indicar´ en el asunto Ficheros que se a borrar´ n en breve y contendr´ los nombres de los ficheros para los que haga a a m´ s de 1 semana pero menos de 2 que no se acceden. Los nombres de los a ficheros en los dos mensajes deber´ n estar ordenados alfab´ ticamente. Para a e el env´o de los mensajes de correo electr´ nico se emplear´ la orden: mail ı o a direcci´ n correo -s asunto Para realizar las acciones requeridas, el o programa deber´ crear procesos y tuber´as de acuerdo al esquema que se a ı muestra en la figura 5.1. Figura 5.1: Esquema de funcionamiento. ´ F´jate en que un unico proceso recorre el directorio /tmp y escribe en una ı tuber´a los nombres de los ficheros y directorios que borra y en otra tuber´a ı ı 39 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 41 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 43. distinta los nombres de los ficheros que se borrar´ n pr´ ximamente. Otros dos a o procesos independientes son los encargados de la ordenaci´ n de los nombres o ı ´ almacenados en las tuber´as y, por ultimo, dos procesos m´ s enviar´ n los a a mensajes de correo electr´ nico. En total, debes manejar 5 procesos y cuatro o tuber´as como se muestra en la figura 5.1. ı 82. Escribe un programa que cree dos procesos de manera que, a partir de dos directorios dados como par´ metros de entrada, uno de los procesos realice a una b´ squeda de los ficheros con terminaci´ n .c y .h que se encuentren a u o ´ partir del primer directorio dado (deber´ s recorrer el arbol de directorios) y a env´e su ruta a trav´ s de una tuber´a a un segundo proceso que crear´ una ı e ı a copia en el segundo directorio. La copia s´ lo se debe realizar si se dan las o dos siguientes condiciones: El fichero encontrado no existe en el segundo directorio. ´ El fichero existe en el segundo directorio, pero el tiempo de ultima modificaci´ n de la copia es anterior al del original. o Para realizar la copia de cada fichero otro proceso deber´ ejecutar el siguiente a comando: cp ruta fichero segundo directorio 83. Escribe un programa en C que convierta ficheros en formato postscript a for- @ibaumo mato pdf. El programa recibir´ como par´ metros una serie de nombres de a a directorios y, para cada uno de ellos, deber´ crear un proceso que lo recorra a recursivamente. Todos estos procesos deben ejecutarse en paralelo. Cada vez que se encuentre un fichero cuyo nombre termine en .ps, se considerar´ que a se trata de un fichero en formato postscript y se obtendr´ un fichero equiva- a lente en formato pdf mediante el comando: ps2pdf ruta f ichero.ps ruta f ichero.pdf Una vez generado el fichero pdf, se debe borrar el fichero postscript corres- pondiente. Puedes suponer que el n´ mero de enlaces duros de cada fichero u postscript ser´ siempre uno. a Antes de la finalizaci´ n de cada proceso, se deber´ informar de los siguientes o a aspectos: - N´ mero de ficheros transformados. u - Ahorro de espacio en disco medido en n´ mero de bloques. u - Tiempo total en segundos que se ha empleado en procesar el directorio correspondiente. 84. Escribe un programa en C que realice una simulaci´ n de la asignaci´ n de o o grupos de pr´ cticas a los estudiantes matriculados en una determinada asig- a natura. El programa recibir´ como par´ metros en la l´nea de comandos: a a ı 40 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 42 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 44. - el n´ mero de estudiantes matriculados en la asignatura, u - la cantidad de grupos de pr´ cticas que existen, y a - el n´ mero de plazas en cada grupo de pr´ cticas. u a Puedes suponer que el n´ mero de estudiantes siempre ser´ menor o igual que u a el n´ mero total de plazas de pr´ cticas disponibles, es decir, que u a numero estudiantes ≤ cantidad de grupos × plazas por grupo El programa deber´ crear una serie de hilos que se ejecuten en paralelo, de a modo que haya un hilo que simule el comportamiento de cada estudiante. Adem´ s, habr´ otro hilo gestor que ser´ el encargado de realizar la asigna- a a a ci´ n de estudiantes a grupos de pr´ cticas, teniendo en cuenta las preferencias o a de cada estudiante. Cada hilo correspondiente a un estudiante debe realizar las siguientes acciones: a) Decidir el orden de preferencia de los grupos de pr´ cticas. a b) Enviar de una en una al gestor una serie de peticiones de inclusi´ n en o los grupos de pr´ cticas seg´ n el orden decidido en el punto anterior. La a u petici´ n que se env´a al gestor debe contener dos datos: o ı @ibaumo - n´ mero de estudiante que hace la petici´ n, y u o - n´ mero de grupo que se solicita. u Para cada petici´ n recibida, el hilo gestor debe mostrar en la pantalla un o mensaje que indique: - Si la acepta porque hay plazas libres en el grupo y el estudiante a´ n no u tiene ning´ n grupo asignado. u - Si la rechaza porque el grupo solicitado no tiene plazas disponibles. - Si la rechaza porque a ese alumno ya se le hab´a asignado otro grupo ı de pr´ cticas (es decir, se le hab´a aceptado una petici´ n anterior). a ı o F´jate en que los estudiantes env´an peticiones para todos los grupos de ı ı pr´ cticas ordenadas seg´ n sus preferencias. El gestor procesar´ todas las so- a u a licitudes y rechazar´ las correspondientes a estudiantes que ya tienen asig- a nado un grupo de pr´ cticas o a grupos que est´ n llenos. a a La comunicaci´ n entre los hilos correspondientes a los estudiantes y el hilo o gestor debe realizarse a trav´ s de un buffer intermedio en el que se podr´ n e a almacenar como m´ ximo 20 peticiones. Debes garantizar que todos los ac- a cesos al buffer sean correctos. Para simplificar la soluci´ n del problema, considera que ya est´ n definidas o a las siguientes variables globales, estructuras y funciones: 41 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 43 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 45. /* Variables globales. IMPORTANTE. Debes inicializarlas en el programa principal seg´n los u par´metros de la l´nea de comandos. a ı */ int num_estudiantes, cantidad_grupos, plazas_por_grupo; /* Tipos de datos */ typedef struct { int num_estudiante; int num_grupo; } TipoPeticion; /* Funciones */ int *decide_preferencias(int num_estudiante); /* Devuelve un vector de enteros en el que los grupos de pr´cticas a est´n ordenados seg´n las preferencias del estudiante */ a u int grupo_asignado(int num_estudiante); /* Devuelve el n´mero de grupo de pr´cticas asignado a un estudiante. u a Si todav´a no se le ha asignado ning´n grupo devuelve -1 */ ı u int hay_plazas_libres(int num_grupo); /* Devuelve 1 si hay plazas libres en el grupo dado o 0 en caso contrario */ void asignar_grupo(int num_estudiante, int num_grupo); /* Asigna el estudiante al grupo indicado */ En concreto, se te pide que proporciones: @ibaumo - La funci´ n que simula el comportamiento de un estudiante. o - La funci´ n que simula el gestor de peticiones. o - El programa principal, que debe incluir todas las inicializaciones que sean necesarias, la creaci´ n de todos los hilos y la espera hasta que o todos ellos terminen. - Todos los tipos, variables, etc. que puedas necesitar y que no aparezcan ya definidos en el enunciado. 85. Escribe un programa en C que imprima los ficheros regulares que encuen- tre en una serie de directorios dados como par´ metros. Para cada directorio a se deber´ crear un proceso que lo recorra recursivamente de modo que to- a dos ellos se ejecuten en paralelo. Los ficheros cuyo tama˜ o sea menor de n 2 Mbytes se enviar´ n a la cola de impresi´ n ps1 y el resto se enviar´ a la a o a cola de impresi´ n ps2. Para enviar un fichero a una cola de impresi´ n se de- o o ber´ ejecutar el siguiente comando: lpr -P cola fichero. Antes de la a finalizaci´ n del programa se deber´ indicar el tiempo total empleado en la o a ejecuci´ n del mismo. o NOTA: Se incluye una versi´ n de la funci´ n de recorrido recursivo de un o o directorio: 42 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 44 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 46. void recorre(char ∗nombredir) { DIR ∗d; struct dirent ∗entrada; struct stat datos; char ∗ruta; printf(empiezo a recorrer %sn, nombredir); d= opendir(nombredir); if (d== NULL) { printf(Error al abrir el directorion); return; } entrada= readdir(d); while (entrada!= NULL) { if (strcmp(entrada-d name, .) strcmp(entrada-d name, ..)) { ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2); sprintf(ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta, datos); if (S ISDIR (datos.st mode)) recorre (ruta); printf (Procesando %sn, ruta); free (ruta); } entrada= readdir(d); } closedir(d); } @ibaumo 86. Se desea realizar una simulaci´ n de una granja de gallos en la que hay dos o tipos de gallos: dom´ sticos y salvajes. En la granja, la vida de un gallo cual- e quiera consiste b´ sicamente en comer, beber y dormir en este orden. Para a realizar la acci´ n de beber se accede a una fuente de agua com´ n para todos o u los gallos y se evita que un gallo salvaje se junte con gallos dom´ sticos o con e otros gallos salvajes mientras dure la acci´ n. Por contra, un gallo dom´ stico o e si que puede realizar la acci´ n de beber junto a otros gallos dom´ sticos. Res- o e pecto a las acciones de comer y dormir no se establece ninguna condici´ n. o La granja cuenta con un total de 30 gallos, 25 de ellos dom´ sticos y el resto e salvajes. Utiliza el programa que se acompa˜ a para resolver las siguientes n cuestiones: a) En primer lugar, se desea mejorar la funci´ n dormir de manera que aho- o ra tendr´ dos par´ metros de entrada: void dormir (int id, int tiempo);. a a La variable id es un identificador del gallo y tiempo ser´ el tiempo que a va a dormir (un valor entero aleatorio entre 7 y 10). Modifica el progra- ma principal de manera que, para cada gallo de la simulaci´ n, se env´e o ı ambos par´ metros a las funciones correspondientes galloDomestico y a ´ galloSalvaje, y modifica estas tambi´ n de forma conveniente. e b) Realiza las modificaciones oportunas de manera que se simule la vida de los gallos dom´ sticos y salvajes tal y como se explica en el enuncia- e do. 43 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 45 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 47. c) Limita el n´ mero de gallos dom´ sticos realizando la acci´ n de beber al u e o mismo tiempo a 6. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include time.h #define N 30; /∗ simula la vida de un gallo salvaje ∗/ void ∗galloSalvaje (void ∗nada){ while (1) { comer(); /∗ funci´n que simula la acci´n de comer ∗/ o o beber(); /∗ funci´n que simula la acci´n de beber ∗/ o o dormir(); /∗ funci´n que simula la acci´n de dormir ∗/ o o } pthread exit(NULL); } /∗ simula la vida de un gallo dom´stico ∗/ e void ∗galloDomestico (void ∗nada){ while (1) { comer(); /∗ funci´n que simula la acci´n de comer ∗/ o o beber(); /∗ funci´n que simula la acci´n de beber ∗/ o o dormir(); /∗ funci´n que simula la acci´n de dormir ∗/ o o @ibaumo } pthread exit(NULL); } int main (int argc, char ∗argv[]) { pthread t th[N]; int i; for (i= 0; i 25; i++) /∗ crea los gallos dom´sticos ∗/ e pthread create (th[i], NULL, galloDomestico, NULL); for (i= 25; i N; i++) /∗ crea los gallos salvajes ∗/ pthread create (th[i], NULL, galloSalvaje, NULL); for (i= 0; i N; i++) pthread join(th[i], NULL); exit(0); } 87. Escribe un programa en C que ejecute en paralelo cuatro hilos. De ellos, tres ser´ n productores de datos y uno consumidor. Los hilos se comunicar´ n a a a trav´ s de un buffer intermedio en el que se podr´ n almacenar como m´ ximo e a a 5 datos. Cada hilo productor se encarga de generar como m´ ximo 1000 n´ meros alea- a u torios. Para cada n´ mero generado, comprueba si es un n´ mero primo y, de u u ser as´, lo almacena en el buffer. El hilo consumidor extrae n´ meros del buf- ı u fer y escribe en pantalla aquellos n´ meros para los que la suma de sus d´gitos u ı 44 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 46 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 48. sea impar. El programa terminar´ cuando el hilo consumidor haya escrito cincuenta a n´ meros en pantalla o cuando cada productor haya generado sus 1000 n´ me- u u ros aleatorios. Antes de terminar, el programa informar´ de la cantidad de a n´ meros primos procesados y la cantidad de n´ meros aleatorios generados. u u Puedes considerar que las siguientes funciones ya est´ n definidas: a int numero_aleatorio(void); int es_primo(int numero); int suma_digitos(int numero); 88. Escribe un programa para limpiar el directorio /tmp. Recorriendo todos los subdirectorios que se encuentren a partir de /tmp, el programa debe eliminar todos los ficheros regulares que pertenezcan al usuario que ejecuta el pro- grama y cuyo tama˜ o sea superior a 2 Mbytes. Adem´ s, se deben eliminar n a los directorios que ya estaban vac´os o queden vac´os al eliminar los ficheros ı ı que conten´an. Tambi´ n se deben identificar los ficheros regulares que ocu- ı e pen m´ s de 1 Mbyte pero menos de 2 Mbytes para informar al usuario de a que esos ficheros est´ n ocupando una gran cantidad de espacio en disco. a El programa recibir´ como par´ metro una direcci´ n de correo electr´ nico a a a o o la que enviar´ dos mensajes. El primer mensaje indicar´ en el asunto Fiche- a a ros borrados de /tmp y contendr´ el nombre de cada fichero o directorio que a @ibaumo se haya eliminado. El segundo mensaje indicar´ en el asunto Ficheros que a ocupan mucho espacio en /tmp y contendr´ el nombre y tama˜ o en bytes de a n cada fichero cuyo tama˜ o est´ entre 1 y 2 Mbytes. n e Para el env´o de los mensajes de correo electr´ nico se emplear´ la orden: ı o a mail direcci´ n correo -s asunto o Para realizar las acciones requeridas, el programa deber´ crear procesos y a tuber´as de acuerdo al esquema que se muestra en la figura 5.2. ı Figura 5.2: Esquema de funcionamiento. ´ F´jate en que un unico proceso recorre el directorio /tmp y escribe en una ı tuber´a los nombres de los ficheros y directorios que borra y en otra tuber´a ı ı distinta los nombres de los ficheros que ocupan m´ s de 1 Mbyte. Otros dos a 45 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 47 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 49. procesos independientes son los encargados de enviar los mensajes de correo electr´ nico. En total, debes manejar 3 procesos y 2 tuber´as como se muestra o ı en la figura. 89. Un programador quiere simular el movimiento de camiones y barcos en una estaci´ n petroqu´mica. Los barcos llegan a la estaci´ n para descargar de sus o ı o bodegas el producto crudo que posteriormente se refina y se carga en los tanques de los camiones que van llegando a la estaci´ n. Las condiciones de o funcionamiento de la estaci´ n que ha de tener en cuenta el programador son: o a) La estaci´ n tiene capacidad para atender a tantos camiones como lle- o guen. b) La estaci´ n tiene capacidad para atender a los barcos de uno en uno. o c) Mientras se atiende a un barco no se puede atender a nuevos camiones pero s´ a los camiones que hubiesen ya en la estaci´ n. ı o En base a estas condiciones, el programador escribe el siguiente c´ digo: o #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h @ibaumo #define N vehiculos 200 sem t estacion; void ∗camion (void ∗ nada) { long int n= (long int) pthread self(); printf (Llega camion: %ldn, n); sem wait(estacion); printf (Se atiende camion: %ldn, n); sleep(random() %3+2); /∗ tiempo invertido en atender al camion ∗/ printf (Sale camion: %ldn, n); pthread exit(NULL); } void ∗barco (void ∗ nada) { long int n= (long int) pthread self(); printf (Llega barco: %ldn, n); sem wait(estacion); printf(Se atiende barco: %ldn, n); sleep(random() %5+5); /∗ tiempo invertido en atender al barco ∗/ printf (Sale barco: %ldn, n); sem post(estacion); pthread exit(NULL); } int main(int argc, char ∗argv[]) { int i; pthread t th; 46 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 48 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 50. for (i= 0; i N vehiculos; i++) { sleep(random() %3); if (random() %100 95) pthread create(th, NULL, camion, NULL); else pthread create(th, NULL, barco, NULL); } for (i= 0; i N vehiculos; i++) pthread join(th, NULL); return 0; } Se pide: a) Puesto que el c´ digo anterior contiene errores y no satisface las tres o condiciones descritas en el enunciado, corrige los errores e indica las modificaciones necesarias para que se satisfagan. b) Haz las modificaciones oportunas (al programa resultado del apartado anterior) para que, sin dejar de cumplirse las condiciones de funciona- miento a) y b), se cumpla tambi´ n la siguiente nueva condici´ n: e o 1) Mientras se atiende a un barco no se puede atender a nuevos ca- miones y el barco s´ lo puede ser atendido cuando no hayan ca- o miones utilizando la estaci´ n. o @ibaumo ´ 90. Escribe un programa que ejecute la siguiente l´nea de ordenes igual que lo ı har´a un int´ rprete de comandos: ı e grep palabra file1 | sort -r | uniq file salida y que adem´ s nos diga cu´ nto tiempo (en segundos) ha tardado en ejecu- a a tarse completamente. Tanto file1, file salida como palabra ser´ n par´ metros a a dados por tu programa en la l´nea de comandos en ese orden. ı 91. Simula el movimiento de personas que entran y salen de una sucursal banca- ria teniendo en cuenta las siguientes condiciones. En dicha sucursal, durante el horario de atenci´ n al p´ blico, un furg´ n blindado puede llegar para la o u o carga y descarga de dinero. Para que se realice esta operaci´ n, es necesario o que no haya clientes en el interior de la sucursal, por lo que los guardias de seguridad del furg´ n deben esperar a que la sucursal se encuentre vac´a an- o ı tes de iniciar la operaci´ n. La sucursal puede atender a tantos clientes como o lleguen, no hay l´mite de capacidad. Utiliza el programa que se acompa˜ a, ı n que contiene alg´ n error, y da dos soluciones al problema, una por cada una u de las siguientes condiciones respecto al momento de llegada del furg´ n a la o sucursal: a) Que no se impida la entrada de nuevos clientes a la sucursal mientras existan clientes en su interior. b) Que s´ se impida la entrada de nuevos clientes a la sucursal. ı 47 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 49 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 51. (Recuerda que en ambos casos, la operaci´ n no puede empezar hasta que la o sucursal est´ sin clientes, como ya se deja claro en el enunciado) e #include stdlib.h #include stdio.h #include semaphore.h #include pthread.h #include unistd.h #include time.h #define N hilos 200 void ∗cliente (void ∗n){ int id= ∗(int ∗)n; sleep (random() %100); printf (Llega el cliente %dn, id); sleep (random() %3+2); /∗ tiempo de espera en la cola ∗/ printf (Se atiende al cliente: %dn, id); sleep (random() %3+2); /∗ tiempo invertido en la operacion ∗/ printf (Sale el cliente %dn,id); pthread exit(NULL); } void ∗furgon (void ∗n){ @ibaumo int id= ∗(int ∗)n; sleep (random() %100); printf (LLega el furgon %dn, id); printf (Se atiende a los guardias %dn, id); sleep (random() %5 + 5); /∗ tiempo invertido en la operacion ∗/ printf (Se va el furgon %dn,id); pthread exit(NULL); } int main ( int argc, char ∗ argv[]) { pthread t hilo; int i, furgon creado= 0; for (i= 0; i N hilos; i++) if (furgon creado== 1) pthread create(hilo, NULL, cliente, (void ∗) i); else if (random() %100 95) pthread create(hilo, NULL, cliente, (void ∗) i); else { pthread create(hilo, NULL, furgon, (void ∗) i); furgon creado= 1; } return 0; } 92. Se desea realizar una implementaci´ n en C del problema cl´ sico del productor- o a consumidor. Las caracter´sticas propias de esta implementaci´ n son: ı o 48 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 50 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 52. Los hilos se comunican a trav´ s de un b´ ffer intermedio de capacidad e u 10. El hilo productor produce un n´ mero aleatorio de datos. u El hilo consumidor escribe el n´ mero consumido en la pantalla. u El programa termina cuando se hayan consumido los datos producidos. En concreto, se pide: a) Escribe el programa principal que: crea, inicializa y destruye los sem´ fo- a ros; crea dos hilos, uno productor y otro consumidor; espera a que se cumpla la condici´ n de terminaci´ n del programa. o o b) Escribe el c´ digo del hilo productor y del consumidor. o c) Escribe las modificaciones oportunas para que en lugar de un hilo pro- ductor hayan tres que se ejecuten en paralelo y garantizando que se consumen todos los datos. d) Escribe las modificaciones oportunas para que en lugar de un hilo con- sumidor hayan dos que se ejecuten en paralelo (es decir, tendremos tres productores y dos consumidores). NOTA: Se incluye una versi´ n incompleta del c´ digo. o o @ibaumo #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include time.h #define MAX 10 int buffer[MAX]; int pos productor= 0, pos consumidor= 0; int menos uno= 0; int genera dato(void); int numero aleatorio(void); void ∗productor (void ∗nada) { int i, dato, n= numero aleatorio(); for(i=0; i n; i++){ dato= generar dato(); sleep(random() %2); buffer[pos productor]= dato; pos productor= (pos productor+1) %MAX; } buffer[pos productor]= -1; pos productor= (pos productor+1) %MAX; pthread exit(NULL); } 49 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 51 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 53. void ∗consumidor (void ∗nada) { int i,dato; while(menos uno!= 1){ dato= buffer[pos consumidor]; pos consumidor= (pos consumidor+1) %MAX; if (dato== -1) menos uno++; printf ( %d , dato); sleep(random( %2)); } pthread exit(NULL); } 93. Escribe un programa en C que, a partir de una serie de directorios que se pro- porcionan como par´ metros, los recorra recursivamente y calcule cu´ ntos en- a a laces simb´ licos hay dentro de ellos. El programa debe crear un hilo por cada o directorio dado, de modo que el recorrido de cada uno de ellos se ejecute en paralelo con el resto. Por simplicidad, se considerar´ que nunca habr´ m´ s a a a de 10 directorios como par´ metros. Tanto para los directorios dados como a par´ metros como para los que aparezcan en el recorrido recursivo de los a mismos, s´ lo se deben tener en cuenta aquellos directorios que pertenezcan o al usuario que ejecuta el programa. El resto de directorios simplementen se ignorar´ n. a Nota. No se pide el n´ mero de enlaces que hay en cada uno de los directorios u @ibaumo dados, sino la suma de todos ellos. Es decir, el resultado del programa debe ´ ser un unico n´ mero. u 94. Se desea escribir un programa que implemente una primera aproximaci´ n a o la generaci´ n de un cierto tipo de claves criptogr´ ficas. Para ello, se deben o a encontrar pares de n´ meros p y q tales que: u p y q sean primos; (p − 1)/2 y (q − 1)/2 tambi´ n sean primos. e Si se cumplen estas dos condiciones, entonces el producto p ∗ q nos propor- ciona una clave criptogr´ fica. Para resolver el problema planteado se utiliza a una estrategia productor-consumidor mediante tres procesos que se ejecutan en paralelo de la siguiente forma: Dos procesos productores se encargan de analizar secuencialmente to- dos los n´ meros de un rango dado para averiguar cu´ les de ellos son u a primos. Un proceso consumidor que, repetidamente, toma un par cualquiera de n´ meros primos de los encontrados por los productores y comprueba u si dicho par de n´ meros cumplen los requisitos necesarios para generar u una clave criptogr´ fica. En caso afirmativo, muestra por pantalla los a dos n´ meros utilizados y el valor de la clave criptogr´ fica generada. En u a 50 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 52 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 54. cualquier caso, estos dos n´ meros utilizados ser´ n descartados y no se u a volver´ n a considerar. a Al acabar la ejecuci´ n, el programa debe indicar la cantidad total de n´ meros o u primos que han encontrado los productores, as´ como el n´ mero de claves ı u criptogr´ ficas generadas. a Escribe un programa en C que proporcione una soluci´ n v´ lida al problema o a utilizando tuber´as. ı 95. Resuelve el ejercicio 94 utilizando 3 hilos (2 productores y 1 consumidor) que ahora se comunican a trav´ s de un buffer intermedio de capacidad 20 e elementos en lugar de utilizar tuber´as. La sincronizaci´ n en la ejecuci´ n de ı o o los hilos se debe realizar mediante sem´ foros. a 96. Escribe un programa que, a partir de un directorio dado como par´ metroa comprima y a˜ ada al fichero /tmp/comprimido.zip todos los ficheros regu- n ´ lares que encuentre a partir de dicho directorio (deber´ recorrer el arbol de a directorios a partir de dicho directorio) tales que: Pertenezcan al usuario que ejecuta el programa. ´ Se hayan modificado desde la ultima hora (medida desde el inicio de la @ibaumo ejecuci´ n del programa). o Para comprimir un fichero fich y a˜ adirlo al fichero /tmp/comprimido.zip uti- n liza el programa zip de la siguiente forma: $ zip /tmp/comprimido.zip fich. Ten en cuenta que no se pueden hacer varias acciones zip sobre el mismo ar- chivo de manera simult´ nea. Adem´ s, por cada fichero regular que encuen- a a tres que cumpla las condiciones anteriores deber´ s enviar su ruta a trav´ s a e de una tuber´a a otro proceso que crear´ un fichero llamado usuario.log que ı a contendr´ un informe ordenado, utiliza el comando sort, de las rutas de los a ficheros regulares a˜ adidos al archivo zip. n 97. En una reuni´ n de atletismo, hay tres tipos de atletas participantes. Por un o lado los lanzadores de jabalina, por otro los lanzadores de martillo y por ´ ultimo los corredores. A primera hora del d´a se les da acceso libre a las ins- ı talaciones para entrenar. Por seguridad, se han establecido unas restricciones de uso de las instalaciones: a) Un atleta lanzador de martillo o de jabalina debe esperar para entrar en las instalaciones a que no haya ning´ n atleta, sea del tipo que sea, u utiliz´ ndolas. a b) Si hay un atleta lanzador de jabalina o de martillo utilizando las insta- laciones, un nuevo atleta que llegue, sea del tipo que sea, debe esperar para entrar en las instalaciones a que el que ya hay la abandone. 51 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 53 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 55. c) Si en las instalaciones hay alg´ n atleta corredor y llega un nuevo atle- u ta corredor, este entrar´ en las instalaciones incluso aunque hubiesen a atletas lanzadores esperando para entrar. Se pide: Completa el c´ digo que se te da a continuaci´ n de forma que se simule o o ´ el comportamiento descrito en el enunciado. Las ordenes printf deben permanecer en tu soluci´ n. Sit´ alas donde debas. o u Modifica el c´ digo soluci´ n del apartado anterior para que se respete o o el orden de llegada de los atletas a las instalaciones. De esta forma, si llega un nuevo atleta corredor habiendo atletas lanzadores esperando, el atleta corredor deber´ esperar a que entren y salgan de las instalaciones a ´ los lanzadores que llegaron antes que el, incluso aunque en el momento de la llegada hubiesen atletas corredores en las instalaciones. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include sys/syscall.h #define N atletas 30 @ibaumo void ∗corredor (void ∗ nada) { int n= (int) syscall(SYS gettid); printf (Llega corredor: %dn, n); printf (Entra en las instalaciones el corredor %dn, n); sleep (random() %3); /∗ tiempo invertido en usarlas ∗/ printf (Sale de las instalaciones el corredor: %dn, n); pthread exit(NULL); } void ∗jabalino (void ∗ nada) { int n= (int) syscall(SYS gettid); printf (Llega lanzador de jabalina: %dn, n); printf (Entra en las instalaciones el jabalino %dn, n); sleep (random() %3+2); /∗ tiempo invertido en usarlas ∗/ printf (Sale de las instalaciones el jabalino: %dn, n); pthread exit(NULL); } void ∗martillo (void ∗ nada) { int n= (int) syscall(SYS gettid); printf (Llega lanzador de martillo: %dn, n); printf (Entra en las instalaciones el martillo %dn, n); sleep (random() %3+2); /∗ tiempo invertido en usarlas ∗/ printf (Sale de las instalaciones el martillo: %dn, n); pthread exit(NULL); } 52 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 54 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 56. int main (int argc, char ∗argv[]) { int num; pthread t th[N atletas]; for (num= 0; num N atletas; num++) { sleep(random() %3); if (random() %100 66) pthread create(th[num], NULL, corredor, NULL); else if (random() %100 82) pthread create(th[num], NULL, jabalino, NULL); else pthread create(th[num], NULL, martillo, NULL); } for (num= 0; num N atletas; num++) pthread join(th[num], NULL); return 0; } 98. En un concurso televisivo de la canci´ n denominado Egovision participan o grupos musicales en representaci´ n de diferentes pa´ses. Despu´ s de las ac- o ı e tuaciones, comienza la fase de la votaci´ n. En esta fase, cada persona del o p´ blico vota enviando un SMS indicando el pa´s y la puntuaci´ n entre 0 y u ı o 10. Durante la fase de votaci´ n, cada pa´s participante puede consultar el o ı @ibaumo estado de las votaciones cuando quiera y cuantas veces desee. Escribe un programa en C que realice una simulaci´ n de este proceso y que adem´ s o a satisfaga las siguientes condiciones: Utiliza un vector de enteros, de dimensi´ n el n´ mero de pa´ses, para o u ı almacenar los puntos que cada pa´s recibe y ll´ malo puntuaciones. ı a La simulaci´ n genera un total de 100 hilos. o Cada hilo generado ser´ de tipo voto con una probabilidad del 90 % o a de tipo consulta con una probabilidad del 10 %. Cada hilo de tipo voto recibe dos datos generados de forma aleatoria, el pa´s votado (representado por un identificador de tipo entero) y una ı puntuaci´ n, y acumula la nueva puntuaci´ n del pa´s indicado a la que o o ı ya hay en el vector puntuaciones. Cada hilo de tipo consulta recibe un dato generado de forma aleatoria: el pa´s que realiza la consulta. Se debe permitir que varias consultas ı se puedan realizar de forma simult´ nea garantizando la coherencia de a los datos mostrados, es decir, que si varios pa´ses realizan consultas al ı mismo tiempo, entonces todos deben mostrar el mismo resultado. Para comprobar visualmente la simulaci´ n sit´ a en el c´ digo para cada o u o tipo de hilo la impresi´ n de los mensajes, que se facilitan a continua- o ci´ n, de forma correcta. o 53 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 55 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 57. #define NHILOS 100 #define PAISES 10 char paises[PAISES][10]={Espa˜ a, Portugal, Francia, Ucrania, n Letonia, Servia, Israel, Alemania, Italia, Holanda}; int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0}; funcion voto { imprime(Voto al pais %s %d puntosn,paises[pais],puntos); imprime(Ya he votado al pais %s %d puntosn,paises[pais],puntos); } funcion consulta { imprime (El pais %s realiza la consultan,paises[pais]); Para (int i=0; i PAISES;i++) imprime(( %s, %d)n,paises[i],puntuaciones[i]); imprime(El pais %s termina la consultan,paises[pais]); } 99. En un concurso televisivo de la canci´ n denominado Egovision participan o grupos musicales en representaci´ n de diferentes pa´ses. Despu´ s de las ac- o ı e tuaciones, comienza la fase de la votaci´ n. En esta fase, cada persona del o @ibaumo p´ blico vota enviando un SMS indicando el pa´s y la puntuaci´ n entre 0 y u ı o 10. Escribe un programa en C que realice una simulaci´ n de este proceso y o que adem´ s satisfaga las siguientes condiciones: a Utiliza un vector de enteros, de dimensi´ n el n´ mero de pa´ses, para o u ı almacenar los puntos que cada pa´s recibe y ll´ malo puntuaciones. ı a La simulaci´ n genera N procesos nuevos que en paralelo emiten un o voto cada uno de ellos. Una tuber´a comunica los N procesos nuevos con el proceso principal. ı Cada proceso que emite un voto genera dos datos de forma aleatoria: el pa´s al que vota (un identificador de tipo entero) y la puntuaci´ n co- ı o rrespondiente. Ambos son enviados por la tuber´a al proceso principal. ı El proceso principal actualiza el resultado de la votaci´ n a medida que o le llegan los votos por la tuber´a. Una vez recogidos todos los votos, ı el resultado final se muestra ordenado (ver ejemplo a continuaci´ n). o Para conseguir la ordenaci´ n se env´a una l´nea de texto por pa´s, con o ı ı ı el formato del ejemplo, mediante una nueva tuber´a a un proceso que ı hace la ordenaci´ n de los datos recibidos mediante la orden sort -r. o 156 puntos, Espa˜a n 150 puntos, Alemania 135 puntos, Holanda . . 54 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 56 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 58. No deben aparecer ni procesos hu´ rfanos ni procesos zombies. e #define N 100 #define PAISES 10 char paises[PAISES][10]={Espa˜ a, Portugal, Francia, Ucrania, n Letonia, Servia, Israel, Alemania, Italia, Holanda}; int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0}; 100. Se desea conocer el n´ mero de nodo-i de cada uno de los ficheros que en un u sistema dado tengan un tama˜ o superior a 1024 bloques. Tambi´ n se quiere n e saber cu´ ntos ficheros satisfacen esta condici´ n. Escribe un programa en C a o que, para conseguir ambos objetivos, act´ e de la siguiente manera: u La b´ squeda de ficheros comienza siempre a partir de un directorio u dado como par´ metro de entrada. a Se podr´ n especificar varios directorios como par´ metros de entrada. a a El proceso inicial deber´ crear tantos procesos de b´ squeda como di- a u rectorios especificados como par´ metros de entrada y deber´ n ejecu- a a ´ tarse en paralelo tanto entre ellos como con el mismo. De esta manera, cada proceso creado realizar´ la b´ squeda recursiva de ficheros en el a u ´ arbol de directorios de uno de los directorios dados como par´ metros a @ibaumo de entrada. Cuando un proceso de b´ squeda encuentre un fichero que satisfaga la condi- u ci´ n dada (tama˜ o superior a 1024 bloques), enviar´ su n´ mero de nodo-i a o n a u trav´ s de una tuber´a a un proceso que realizar´ una ordenaci´ n de todos los e ı a o n´ meros recibidos utilizando el comando del sistema sort. Cuando un proce- u u ´ so de b´ squeda haya terminado de recorrer el arbol de directorios, enviar´ al a proceso inicial, y a trav´ s de otra tuber´a, el n´ mero de ficheros encontrados e ı u que han cumplido la condici´ n dada. Una vez todos los procesos de b´ sque- o u da creados hayan terminado, el proceso inicial informar´ del total de ficheros a encontrados. 55 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 57 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 59. Cap´tulo 6 ı Soluciones 1. La jerarqu´a resultante se puede observar en la figura 6.1. ı ı del bucle en la que se crea. @ibaumo Figura 6.1: Jerarqu´a en profundidad donde para cada proceso se indica la iteraci´ n o Aparecen mensajes repetidos porque la orden printf, la que hay dentro del bucle, la ejecuta cada proceso hijo una primera vez tras ser creado como resultado de la llamada al sistema fork que hay justo en la l´nea anterior del ı printf, y una segunda vez en la siguiente iteraci´ n del bucle (excepto en el o ´ caso de encontrarse en su ultima iteraci´ n). o Se observa que los procesos terminan en el orden contrario al que se han ´ ´ creado, es decir, primero termina el ultimo proceso creado y el ultimo proce- so en terminar es el inicial. Esto ocurre gracias a la llamada al sistema wait que cambia el estado del proceso padre a bloqueado hasta que el proceso hijo termine. 2. La jerarqu´a resultante se puede observar en la figura 6.2. ı ´ Se observa que el proceso padre es siempre el ultimo en terminar. Esto es debido a que la llamada al sistema wait, que hace que el proceso padre pase a estado bloqueado hasta que un proceso hijo termine, se encuentra dentro de un bucle que va a hacer que se llame tantas veces como procesos hijos cre´ . o 57 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 58 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 60. Figura 6.2: Jerarqu´a en anchura donde para cada proceso se indica la iteraci´ n del ı o bucle en la que se crea. Sin embargo, los procesos hijos acaban en cualquier orden dependiendo del retardo que cada uno realice con la orden sleep. 3. La jerarqu´a resultante se puede observar en la figura 6.3. ı @ibaumo ´ Figura 6.3: Arbol de procesos donde para cada proceso se indica la llamada a fork responsable de su creaci´ n. o 4. La jerarqu´a resultante se puede observar en la figura 6.4. ı 5. La jerarqu´a resultante se puede observar en la figura 6.5. ı 6. La jerarqu´a resultante se puede observar en la figura 6.6. A continuaci´ n se ı o muestra un ejemplo del c´ digo con las llamadas correspondientes. o #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h #define L1 2 #define L2 3 int main (int argc, char ∗argv[]) { int cont1, cont2; pid t pid; for (cont2= 0; cont2 L2; cont2++) { for (cont1= 0; cont1 L1; cont1++) { pid= fork(); if (pid== 0) break; 58 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 59 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 61. ´ Figura 6.4: Arbol de procesos donde para cada proceso se indica la iteraci´ n en la o que se crea y si realiza el cambio de imagen (aquellos que contienen ”ls”). ´ @ibaumo Figura 6.5: Arbol de procesos donde para cada uno se indica la iteraci´ n en la que se crea y la llamada a fork responsable de su creaci´ n. o o } if (pid!= 0) break; } printf (Soy el proceso de PID %d y mi padre tiene %d de PID.n, getpid(), getppid()); if (pid!= 0) for (cont1= 0; cont1 L1; cont1++) printf (Fin del proceso de PID %d.n, wait (NULL)); return 0; } 7. La jerarqu´a resultante se puede observar en la figura 6.7. A continuaci´ n ı o se muestra el c´ digo para que se produzcan las esperas solicitadas as´ como o ı se informe de los tiempos correspondientes. Se˜ alar que todos los proce- n sos hijos ejecutan la aplicaci´ n kcalc y que la ejecuci´ n de xload nunca se o o produce. 59 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 60 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 62. ´ Figura 6.6: Arbol de procesos donde para cada uno se indica la iteraci´ n en la que o se crea. #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h #include time.h int main (int argc, char ∗argv[]) { @ibaumo int i, j; pid t pid, nuevo, nuevo1; time t ini, fin; ini= time(NULL); for (i= 0; i 2; i++){ pid= getpid(); for (j= 0; j i+2; j++){ nuevo= fork(); if(nuevo== 0){ break; nuevo1= fork(); if(nuevo1== 0) execlp (xload, xload, NULL); } } if (pid!= getpid()) execlp (kcalc, kcalc, NULL); } for (i= 0; i 2; i++) for (j= 0; j i+2; j++){ wait(NULL); printf (Tiempo en ejecuci´ n de kcalc: %ldn, time(NULL)-ini); o } printf (Tiempo total: %ldn, time(NULL)-ini); return 0; } 60 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 61 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 63. Figura 6.7: Jerarqu´a donde para cada proceso hijo se indica la iteraci´ n del bucle ı o en la que se crea. 8. A continuaci´ n se muestra el trozo de c´ digo que habr´a que insertar en el o o ı programa del enunciado donde figura el comentario de /* completar aqu´ */. ı for (prof= 0; prof profundidad-1; prof++) if (fork()!= 0) /∗ jerarqu´a en profundidad ∗/ ı break; /∗ if ((prof!= 0) (prof %2== 0)) ∗/ /∗ ampliaci´n ∗/ o for (anch= 0; anch anchura-1; anch++) if (fork()== 0) /∗ jerarqu´a en anchura ∗/ ı break; 9. for (cont1= 0; cont1 n; cont1++){ pid= getpid(); for(cont2= 0;cont2 cont1+2; cont2++){ nuevo= fork(); @ibaumo if (nuevo == 0) break; } npid= getpid(); if (npid== pid) break; } 10. Para medir el tiempo habr´ que realizar dos llamadas a time(), una antes de a ejecutar prueba.exe y otra despu´ s. Restando los valores obtenidos calcu- e lamos el tiempo que ha transcurrido. Ya que el proceso hijo es quien va a realizar el cambio de imagen, la medici´ n de tiempo la debe realizar el pro- o ceso padre. El proceso padre no toma el valor inicial del tiempo correcto, que est´ inicializado a cero, ya que la linea inicio= time(); la ejecuta el proceso a hijo. La soluci´ n es que dicha l´nea la ejecute el proceso padre poni´ ndola, o ı e por ejemplo, justo antes de la llamada a wait(NULL);. 11. Si la aplicaci´ n kcalc est´ en alguna de las rutas almacenadas por la variable o a de entorno PATH, se producir´ el cambio de imagen en el proceso pasando a a ejecutarse la aplicaci´ n kcalc. En el caso de no encontrarse, la ejecuci´ n o o del proceso continua imprimiendo el mensaje e intentar´ realizar el cambio a de imagen con la aplicaci´ n xload. En el caso de tampoco encontrarla, el o proceso continua su ejecuci´ n imprimiendo un nuevo mensaje y finalizando. o A continuaci´ n se muestra el programa modificado tal y como se solicita en o el enunciado. 61 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 62 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 64. #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h int main (int argc, char ∗argv[]) { pid t pid kcalc, pid xload, pidfin; int num; pid kcalc= fork(); if (pid kcalc== 0) { execlp (kcalc, kcalc, NULL); printf (No se encuentra la aplicaci´ n kcalcn); o exit (0); } pid xload= fork(); if (pid xload== 0) { execlp (xload, xload, NULL); printf (No se encuentra la aplicaci´ n xloadn); o exit (0); } for (num= 0; num 2; num++) { pidfin= wait (NULL); if (pidfin== pid kcalc) printf (Ha terminado kcalcn); @ibaumo else printf (Ha terminado xloadn); } return 0; } 12. #include sys/types.h #include sys/wait.h #include unistd.h #include stdio.h #include stdlib.h #include time.h int main (int argc, char ∗argv[]) { pid t pid kcalc, pid xload, pidfin; int num; time t ini, fin; ini= time (NULL); pid kcalc= fork(); if (pid kcalc== 0) { execlp (kcalc, kcalc, NULL); printf (No se encuentra la aplicaci´ n kcalcn); o exit (0); } pid xload= fork(); 62 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 63 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 65. if (pid xload== 0) { execlp (xload, xload, NULL); printf (No se encuentra la aplicaci´ n xloadn); o exit (0); } for (num= 0; num 2; num++) { pidfin= wait (NULL); fin= time (NULL); if (pidfin== pid kcalc) printf (Ha terminado kcalc, %ld segundosn, fin-ini); else printf (Ha terminado xload, %ld segundosn, fin-ini); } fin= time (NULL); printf (Proceso padre, %ld segundosn, fin-ini); return 0; } 13. #include unistd.h #include stdio.h #include stdlib.h #include sys/types.h #include sys/wait.h #define MAXLON 100 int main (int argc, char ∗argv[]) { @ibaumo char cadena1[MAXLON], cadena2[MAXLON]; int pos; pid t pid; printf (Introduce la cadena 1n); gets (cadena1); printf (Introduce la cadena 2n); gets (cadena2); pid= fork(); if (pid!= 0) { /∗ proceso padre ∗/ for (pos= 0; cadena1[pos]!= ’0’; pos++) { printf ( %c, cadena1[pos]); fflush (stdout); sleep (random() %3); } wait (NULL); /∗ espera a que termine el hijo ∗/ printf (n); } else /∗ proceso hijo ∗/ for (pos= 0; cadena2[pos]!= ’0’; pos++) { printf ( %c, cadena2[pos]); fflush (stdout); sleep (random() %3); } return 0; } 14. #include stdio.h #include unistd.h #include stdlib.h 63 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 64 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 66. #include string.h #include sys/types.h #include sys/wait.h #include stdbool.h int main (int argc, char ∗argv[]) { pid t nuevo; bool fin= false; char nombre[50], esperar[5]; while (!fin) { printf (Nombre: ); scanf ( %s, nombre); if (strcmp(nombre, salir)!= 0) { printf (Esperar? ); scanf ( %s, esperar); nuevo= fork (); if (nuevo!= 0) { /∗ proceso padre ∗/ if (strcmp (esperar, si)== 0) while (nuevo!= wait (NULL)); else printf (PID del proceso hijo %dn, nuevo); } else { /∗ proceso hijo ∗/ if (execlp (nombre, nombre, NULL)== -1) printf (No se ha podido ejecutar. Variable PATH: %sn, getenv (PATH)); exit(0); } } else fin= true; @ibaumo } return 0; } 15. #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/wait.h int main (int argc, char ∗argv[]) { pid t nuevo; if (argc!= 3) { printf (Especfica dos numeros enteros.n); exit (0); } nuevo= fork (); if (nuevo!= 0) { nuevo= fork (); if (nuevo!= 0) { wait (NULL); wait (NULL); printf (Factoriales calculados.n); } else { execl (./factorial, ./factorial, argv[2], NULL); printf (No se encuentra la aplicacion factorialn); exit(0); 64 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 65 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 67. } } else { execl (./factorial, ./factorial, argv[1], NULL); printf (No se encuentra la aplicacion factorialn); exit(0); } return 0; } 16. #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/wait.h int main (int argc, char ∗argv[]) { pid t proceso, proc1; int param; if (argc 2) { printf (Indica los numeros de los que quieres calcular su factorial.n); exit(0); } for (param= 1; param argc; param++) { proceso= fork(); @ibaumo if (param== 1) proc1= proceso; if (proceso== 0) { execl (./factorial, ./factorial, argv[param], NULL); printf (No se encuentra la aplicacion factorialn); exit(0); } } for (param= 1; param argc; param++) { proceso= wait(NULL); if (proceso!= proc1) printf (Proceso de PID %d finalizadon, proceso); } printf (Factoriales calculados.n); return 0; } 17. #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/wait.h #include time.h int main (int argc, char ∗argv[]) { pid t pid; time t inicio, fin; 65 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 66 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 68. if (argc 2) { printf (Indica un programa a ejecutar.n); exit(0); } pid= fork(); if (pid== 0) { execvp (argv[1], argv[1]); printf (No se encuentra la aplicacion %sn, argv[1]); exit(0); } inicio= time (NULL); wait (NULL); fin= time (NULL); printf (Duraci´ n: %ld segundosn, fin-inicio); o return 0; } E/S D2 E/S D1 A1 A2 CPU IR A1 A2 IS IR IS B1 B2 IH1 IR B3 B4 E/S D2 A1 A2 A3 A4 A5 18. E/S D1 B1 CPU IR A1 A2 A3 IR IS IS B5 IR IS IS N @ibaumo E/S D2 E/S D1 CPU IH1 IR IH2 B1 IR IS IS A1 IR IS IS E/S A1 A2 A3 CPU IR A1 A2 A3 IS IR IS B1 B2 B3 IH IR E/S A1 19. CPU B4 B5 B6 IR A1 A2 IS IS IR IH B7 B8 E/S B1 CPU IS IR IS A1 IH IS IR IS B1 IS IS E/S A1 CPU IR A1 A2 A3 IR A4 A5 A6 IR IS IS B1 E/S B1 B2 B3 B4 B5 B6 20. CPU IH IR B2 IS IR IS A1 A2 IR IS IS N E/S CPU IH IR B1 B2 IR B3 IS IS 66 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 67 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 69. E/S A1 A2 A3 A4 A5 A6 CPU IR A1 A2 A3 IR IS B1 B2 IR B3 B4 B5 E/S A7 A8 A9 A10 C1 C2 C3 C4 21. CPU IR C1 C2 C3 IH IR IS A1 IR A2 A3 IH E/S CPU IR C1 IS B6 IR IS A4 IS E/S A1 CPU IR A1 A2 A3 IR IS IS B1 IH IR B2 B3 E/S A1 22. CPU IR A1 IS IS IR IH B4 IS IR IS A1 IS E/S CPU IR IS E/S CPU IR A1 A2 A3 IR A4 A5 A6 IR B1 B2 IS E/S B1 B1 23. CPU IR IH A7 A8 IR A9 A10 A11 IR B1 IS A12 E/S CPU IH IR A13 A14 IR IS B1 IS @ibaumo E/S D2 B1 B2 E/S D1 A1 A2 A3 A4 A5 A6 A7 A8 CPU IR A1 IS IS IR B1 B2 IS IR IS C1 C2 E/S D2 24. E/S D1 CPU IH1 IH2 IR C3 IR B1 B2 B3 IR B4 B5 B6 E/S D2 E/S D1 CPU IR A1 IS IS IR C4 IS IS IR B7 IS IS E/S CPU IR A1 A2 A3 A4 IR A5 A6 A7 A8 IR B1 E/S B1 C1 C2 C3 C4 C5 C6 CPU B2 IS C1 IR IH IS A9 A10 IR A11 A12 A13 25. E/S CPU IH IR B1 B2 B3 IS IR C1 C2 C3 C4 IR E/S CPU IS A14 A15 IS 26. #include unistd.h #include stdlib.h #include stdio.h #include pthread.h 67 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 68 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 70. void ∗ factorial (void ∗ dato) { long long int resultado= 1; int num, n= atoi((char ∗) dato); for (num= 2; num= n; num++) { resultado= resultado∗ num; printf (Factorial de %d, resultado parcial %lldn, n, resultado); sleep (random() %3); } printf (El factorial de %d es %lldn, n, resultado); pthread exit(NULL); } int main (int argc, char ∗argv[]) { pthread t hilo1, hilo2; if (argc!= 3) { printf (Indica dos numeros enteros.n); exit(0); } pthread create (hilo1, NULL, factorial, (void ∗) argv[1]); pthread create (hilo2, NULL, factorial, (void ∗) argv[2]); pthread join (hilo1, NULL); pthread join (hilo2, NULL); printf (Factoriales calculadosn); @ibaumo return 0; } 27. #include unistd.h #include stdlib.h #include stdio.h #include pthread.h void ∗ factorial (void ∗ dato) { long long int resultado= 1; int num, n= atoi((char ∗) dato); for (num= 2; num= n; num++) { resultado= resultado∗ num; printf (Factorial de %d, resultado parcial %lldn, n, resultado); sleep (random() %3); } printf (El factorial de %d es %lldn, n, resultado); pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t hilo[argc-1]; int param; if (argc 2) { printf (Indica los numeros de los que quieres obtener su factorial.n); exit (0); 68 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 69 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 71. } for (param= 0; param argc-1; param++) pthread create (hilo[param], NULL, factorial, (void ∗) argv[param+1]); for (param= 0; param argc-1; param++) { pthread join (hilo[param], NULL); printf (Hilo %d finalizadon, param+1); } printf (Factoriales calculadosn); return 0; } 28. #include stdlib.h #include stdio.h #include pthread.h #include unistd.h #define MAXLON 100 void ∗imprimecadena (void ∗dato) { int pos; char ∗cadena= (char ∗) dato; for (pos= 0; cadena[pos]!= ’0’; pos++) { printf ( %c, cadena[pos]); @ibaumo fflush (stdout); sleep (random() %3); } pthread exit(NULL); } int main (int argc, char ∗argv[]) { pthread t hilo1, hilo2; char cadena1[MAXLON], cadena2[MAXLON]; printf (Introduce la cadena 1n); gets (cadena1); printf (Introduce la cadena 2n); gets (cadena2); pthread create (hilo1, NULL, imprimecadena, (void ∗) cadena1); pthread create (hilo2, NULL, imprimecadena, (void ∗) cadena2); pthread join (hilo1, NULL); pthread join (hilo2, NULL); printf (n); return 0; } 29. #include unistd.h #include stdlib.h #include stdio.h #include pthread.h #include sys/types.h #include sys/stat.h #include fcntl.h 69 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 70 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 72. #define MAXLON 1000 void ∗cuenta (void ∗dato) { int pos, cont= 0, leidos; char ∗nombre= (char ∗) dato, cadena[MAXLON]; int fd; fd= open (nombre, O RDONLY); while ((leidos= read (fd, cadena, MAXLON))!= 0) for (pos= 0; pos leidos; pos++) if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’)) cont++; printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn, nombre, cont); close (fd); pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t hilo; if (argc!= 2) { printf (Indica el nombre de un fichero.n); exit(0); } pthread create (hilo, NULL, cuenta, (void ∗) argv[1]); pthread join (hilo, NULL); return 0; @ibaumo } 30. #include unistd.h #include stdlib.h #include stdio.h #include pthread.h #include sys/types.h #include sys/stat.h #include fcntl.h #define MAXLON 1000 void ∗cuenta (void ∗dato) { int pos, cont= 0, leidos; char ∗nombre= (char ∗) dato, cadena[MAXLON]; int fd; fd= open (nombre, O RDONLY); while ((leidos= read (fd, cadena, MAXLON))!= 0) for (pos= 0; pos leidos; pos++) if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’)) cont++; printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn, nombre, cont); close (fd); pthread exit (NULL); } 70 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 71 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 73. int main (int argc, char ∗argv[]) { pthread t hilo[argc-1]; int param; if (argc 2) { printf (Indica el nombre de uno o varios ficheros.n); exit(0); } for (param= 0; param argc-1; param++) pthread create (hilo[param], NULL, cuenta, (void ∗) argv[param+1]); for (param= 0; param argc-1; param++) pthread join(hilo[param], NULL); return 0; } 31. #include unistd.h #include stdlib.h #include stdio.h #include pthread.h #include sys/types.h #include sys/stat.h #include fcntl.h #define MAXLON 1000 @ibaumo typedef struct { char ∗nombre; int cont; } info; void ∗cuenta (void ∗dato) { int pos, cont= 0, leidos; info ∗misdatos= (info ∗) dato; char cadena[MAXLON]; int fd; fd= open (misdatos-nombre, O RDONLY); while ((leidos= read (fd, cadena, MAXLON))!= 0) for (pos= 0; pos leidos; pos++) if ((cadena[pos]== ’a’) || (cadena[pos]== ’A’)) cont++; misdatos-cont= cont; close (fd); pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t vectorhilos[argc-1]; info vectordatos[argc-1]; int param; if (argc 2) { printf (Indica el nombre de uno o varios ficheros.n); exit(0); } 71 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 72 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 74. for (param= 0; param argc-1; param++) { vectordatos[param].nombre= argv[param+1]; vectordatos[param].cont= 0; pthread create (vectorhilos[param], NULL, cuenta, (void ∗) vectordatos[param]); } for (param= 0; param argc-1; param++) pthread join (vectorhilos[param], NULL); for (param= 0; param argc-1; param++) printf (Fichero %s: %d caracteres ’a’ o ’A’ encontradosn, vectordatos[param].nombre, vectordatos[param].cont); return 0; } 32. #include unistd.h #include stdlib.h #include stdio.h #include pthread.h #include sys/types.h #include sys/wait.h #include sys/stat.h #include fcntl.h #define K 50 typedef struct { @ibaumo char ∗nombre; int inicio; int encontrados; } info; void ∗busca (void ∗datos) { int pos, cont= 0, leidos, fd; info∗ datoshilo= (info ∗) datos; char cadena[K]; sleep (random() %3); fd= open (datoshilo-nombre, O RDONLY); lseek (fd, datoshilo-inicio, SEEK SET); leidos= read (fd, cadena, K); for (pos= 0; pos leidos; pos++) if (cadena[pos]== ’ ’) cont++; close (fd); datoshilo-encontrados= cont; pthread exit (NULL); } void cuentaEspacios (char ∗nombre){ int longitud, pos, nHilos, fd, total= 0; pthread t ∗vectorhilos; info ∗vectordatos; /∗ averigua la longitud del fichero ∗/ fd= open (nombre, O RDONLY); 72 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 73 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 75. longitud= lseek (fd, 0, SEEK END); close (fd); /∗ determina el numero de hilos a crear ∗/ nHilos= longitud/K; if ((longitud % K)!= 0) nHilos++; vectorhilos= (pthread t ∗) malloc (nHilos∗sizeof(pthread t)); vectordatos= (info ∗) malloc (nHilos∗sizeof(info)); for (pos= 0; pos nHilos; pos++) { vectordatos[pos].nombre= nombre; vectordatos[pos].inicio= pos∗ K; vectordatos[pos].encontrados= 0; pthread create (vectorhilos[pos], NULL, busca, (void ∗) vectordatos[pos]); } for (pos= 0; pos nHilos; pos++) { pthread join (vectorhilos[pos], NULL); total+= vectordatos[pos].encontrados; } printf (Fichero %s: %d espacios en blanco encontradosn, nombre, total); free (vectorhilos); free (vectordatos); } int main (int argc, char ∗argv[]) { @ibaumo int numfich; for (numfich= 1; numfich argc; numfich++) if (fork()== 0) { cuentaEspacios (argv[numfich]); exit(0); } for (numfich= 1; numfich argc; numfich++) wait(NULL); return 0; } 33. #include stdio.h #include stdlib.h #include unistd.h #include time.h #include sys/types.h #include sys/wait.h int main (int argc, char ∗argv[]){ int tubo[2]; time t ini= time(NULL), fin; if (fork()== 0){ pipe (tubo); if (fork()== 0){ dup2 (tubo[1],STDOUT FILENO); close (tubo[0]); 73 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 74 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 76. close (tubo[1]); execlp (ls,ls,NULL); }else{ dup2 (tubo[0],STDIN FILENO); close (tubo[0]); close (tubo[1]); execlp (wc,wc,-l,NULL); } } else { wait (NULL); fin= time (NULL); printf (Tiempo invertido: %ld segundosn, fin-ini); } return 0; } 34. El proceso que ejecuta el comando ls redirige la salida estandar utilizando el descriptor de lectura de la tuber´a, en lugar del de escritura. Esto produce un ı error. A su vez, el proceso que ejecuta la orden sort redirige el descriptor de lectura estandard utilizando el descriptor de escritura de la tuber´a. Tambi´ n ı e produce un error. Soluci´ n, cambiar las l´neas siguientes: o ı dup2(tubo[1], STDIN_FILENO); por dup2(tubo[0], STDIN_FILENO); @ibaumo dup2(tubo[0], STDOUT_FILENO); por dup2(tubo[1], STDOUT_FILENO); Y adem´ s, las dos llamadas a close del proceso que va a cambiar su imagen a con el comando sort, ponerlas entre dup2 y execlp para evitar que, cuando ı ı ´ vac´e la tuber´a habiendo terminado el ls, se bloquee por tener el mismo el descriptor de escritura de la tuber´a abierto cuando se produce el cambio de ı imagen. 35. El problema que se produce es debido a que el proceso inicial tiene acceso a la tuber´a y no cierra el descriptor de escritura. En consecuencia, el pro- ı ceso que cambia su imagen al comando wc (que lee de la tuber´a) pasa a ı bloqueado al vaciarla, a´ n cuando haya terminado el que cambia su imagen u al comando ls (que es el que realmente escribe en la tuber´a). ı Para solucionarlo, por ejemplo, y ya que el proceso inicial no va a utilizar la tuber´a, mover la orden pipe justo despu´ s del primer if manteniendo as´ el ı e ı acceso a los otros dos procesos pero evitando que el proceso inicial tenga acceso a la tuber´a. ı 36. El programa pretende realizar el sort de un fichero. Para ello escribe, en primer lugar, el contenido del fichero en una tuber´a. Es en este punto donde ı el proceso puede pasar a estado de bloqueo si se llena la tuber´a, no saliendo ı de este estado al no haber ning´ n proceso que lea de ella y, en consecuencia, u la vac´e. En el caso de que la tuber´a tuviese capacidad para almacenar el ı ı 74 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 75 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 77. contenido completo del fichero, la ejecuci´ n continuar´a y se mostrar´a el o ı ı resultado de ejecutar la orden sort sobre el contenido del fichero. 37. El flujo de informaci´ n de la tuber´a se realiza desde el proceso ls, que act´ a o ı u como proceso hijo y escribe en la tuber´a, hacia el proceso wc que act´ a ı u como proceso padre y lee de la tuber´a. ı Si la cantidad total de informaci´ n escrita en la tuber´a, resultado de la ejecu- o ı ci´ n del comando ls, es inferior al tama˜ o de la tuber´a, y s´ lo en este caso, o n ı o no habr´ problema alguno y se podr´ observar el resultado de la ejecuci´ n a a o de ls | wc -l. Sin embargo, en cuanto la cantidad de informaci´ n superase la capacidad de o la tuber´a, entonces el proceso que escribe pasar´a al estado de bloqueado, ı ı ı ´ del cual no saldr´a ya que el unico proceso que podr´a leer datos de la tuber´a, ı ı el proceso padre, est´ tambi´ n en estado de bloqueo como consecuencia de a e la ejecuci´ n de la orden wait(NULL). o 38. #include stdio.h #include stdlib.h #include sys/types.h #include wait.h #include unistd.h #include sys/stat.h #include fcntl.h @ibaumo int main (int argc, char ∗argv[]) { int tubo1[2], tubo2[2], mifichero; pipe(tubo1); pipe(tubo2); if (fork()== 0) { if (fork()== 0) { dup2 (tubo1[1], STDOUT FILENO); close (tubo1[0]); close (tubo2[0]); close (tubo2[1]); close (tubo1[1]); execlp (paste, paste, argv[1], argv[2], NULL); } else { dup2 (tubo1[0], STDIN FILENO); dup2 (tubo2[1], STDOUT FILENO); close (tubo1[1]); close (tubo2[0]); close (tubo1[0]); close (tubo2[1]); execlp (sort, sort, NULL); } } else { dup2 (tubo2[0], STDIN FILENO); close (tubo1[0]); close (tubo1[1]); close (tubo2[1]); close (tubo2[0]); mifichero= open(argv[3], O WRONLY|O CREAT); dup2 (mifichero, STDOUT FILENO); 75 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 76 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 78. close (mifichero); execlp (nl, nl, NULL); } return 0; } 39. #include stdio.h #include stdlib.h #include sys/types.h #include wait.h #include unistd.h #include sys/stat.h #include fcntl.h int main (int argc, char ∗argv[]) { int tubo1[2], mifichero; pipe(tubo1); if (fork()== 0) { dup2 (tubo1[1], STDOUT FILENO); close (tubo1[0]); close (tubo1[1]); execlp (grep, grep, argv[1], argv[2], NULL); } else if (fork()== 0) { dup2 (tubo1[1], STDOUT FILENO); @ibaumo close (tubo1[0]); close (tubo1[1]); execlp (grep, grep, argv[1], argv[3], NULL); } else { dup2 (tubo1[0], STDIN FILENO); close (tubo1[0]); close (tubo1[1]); mifichero= creat(argv[4], 00644); dup2 (mifichero, STDOUT FILENO); close (mifichero); execlp (wc, wc, -m, NULL); } return 0; } 40. #include stdio.h #include stdlib.h #include sys/types.h #include wait.h #include unistd.h #include string.h #include sys/stat.h #include fcntl.h #define MAXLON 1000 int main (int argc, char ∗argv[]) { int tubo1[2], tubo2[2], fd; int nlinea; 76 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 77 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 79. FILE ∗fich; char linea[MAXLON], cad1[MAXLON], cad2[MAXLON]; pipe(tubo1); pipe(tubo2); if (fork()!= 0) { if (fork()!= 0) { /∗ Separar lineas pares e impares ∗/ close (tubo1[0]); close (tubo2[0]); if (!(fich= fopen (argv[1],r))) { printf (Error al abrir el fichero %sn,argv[1]); exit(0); } nlinea= 1; while (fgets (linea, MAXLON, fich)) { if (nlinea %2== 1) /∗ Impar ∗/ write (tubo1[1], linea, strlen (linea)); else /∗ Par ∗/ write (tubo2[1], linea, strlen (linea)); nlinea++; } fclose (fich); close (tubo1[1]); close (tubo2[1]); wait (NULL); wait (NULL); } else { /∗ impares ∗/ dup2 (tubo1[0], STDIN FILENO); close (tubo1[1]); @ibaumo close (tubo2[1]); close (tubo1[0]); close (tubo2[0]); sprintf (cad1, %s.txt, argv[2]); fd= creat(cad1,00644); dup2 (fd, STDOUT FILENO); close (fd); execlp (grep, grep, argv[2], NULL); } } else { /∗ pares ∗/ dup2 (tubo2[0], STDIN FILENO); close (tubo1[1]); close (tubo2[1]); close (tubo1[0]); close (tubo2[0]); sprintf (cad2, %s.txt, argv[3]); fd= creat (cad2,00644); dup2 (fd, STDOUT FILENO); close (fd); execlp (grep, grep, argv[3], NULL); } return 0; } 41. Es necesario que las tareas 1 y 4 las hagan procesos distintos que se ejecuten en paralelo, ya que, si las realiza el mismo proceso, la tarea 4, que es la que vaciar´a la tuber´a 3, nunca empezar´ mientras no se termine la tarea 1, lo ı ı a que puede producir que la tuber´a 3 se llene y, en consecuencia, los procesos ı que ejecutan el comando grep se bloqueen al escribir sobre la tuber´a llena, ı 77 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 78 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 80. dejando de leer de las tuber´as 1 y 2, y produciendo a su vez que las tuber´as ı ı 1 y 2 puedan llenarse y tambi´ n el bloqueo del proceso que ejecuta la tarea e 1 al intentar escribir sobre una tuber´a llena. ı #include stdio.h #include sys/types.h #include wait.h #include unistd.h #include string.h #include stdlib.h #define MAX 1000 int main(int argc, char ∗argv[]) { int nlinea; FILE ∗fichero; char linea[MAX]; int tubo1[2], tubo2[2], tubo3[2]; if (argc!=4) { printf(Error en el n´ mero de parametrosn); u exit(1); } pipe(tubo1); pipe(tubo2); pipe(tubo3); @ibaumo if (fork()!=0) { if (fork()!= 0) { if (fork()!= 0) { // tarea 4 dup2(tubo3[0], STDIN FILENO); close (tubo1[0]); close (tubo1[1]); close (tubo2[0]); close (tubo2[1]); close (tubo3[0]); close (tubo3[1]); execlp (sort, sort, NULL); } else { // tarea 3 dup2(tubo2[0], STDIN FILENO); dup2(tubo3[1], STDOUT FILENO); close (tubo1[0]); close (tubo1[1]); close (tubo2[0]); close (tubo2[1]); close (tubo3[0]); close (tubo3[1]); execlp (grep, grep, argv[3], NULL); } } else { //tarea 2 dup2(tubo1[0], STDIN FILENO); dup2(tubo3[1], STDOUT FILENO); close (tubo1[0]); close (tubo1[1]); close (tubo2[0]); close (tubo2[1]); close (tubo3[0]); close (tubo3[1]); execlp (grep, grep, argv[2], NULL); } 78 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 79 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 81. } else { //tarea 1 close (tubo1[0]); close (tubo2[0]); close (tubo3[0]); close (tubo3[1]); if (!(fichero= fopen(argv[1],r))) { printf(Error al abrir el fichero %sn,argv[1]); exit(2); } nlinea=0; while (fgets(linea,MAX,fichero)) { if (nlinea %2==0) write(tubo1[1],linea,strlen(linea)); else write(tubo2[1],linea,strlen(linea)); nlinea++; } fclose(fichero); close (tubo1[1]); close (tubo2[1]); } return 0; } 42. No se da situaci´ n de interbloqueo, todos los procesos acabar´ n las secuen- o a cias de c´ digo. La salida por pantalla es la siguiente: 34125. Valor final de o los sem´ foros: los cuatro sem´ foros est´ n a cero. a a a @ibaumo 43. Ocurre situaci´ n de interbloqueo siempre. En el c´ digo A, el proceso se o o bloquea en la llamada al segundo sem wait(s2) mientras que, en el c´ digo o B, el proceso se bloquea en la llamada al segundo sem wait(s1). Hasta alcanzar el punto de interbloqueo, las posibles salidas son 2. Inicial- mente aparecen las cadenas A1 y B1, que pueden salir combinadas de cual- ´ ´ ´ quier manera, es decir, A1B1 o B1A1 o AB11 o BA11. Despu´ s, siempre e saldr´ lo mismo: B2B3A2. a 44. #include unistd.h #include stdlib.h #include stdio.h #include pthread.h #include sys/types.h #include sys/stat.h #include fcntl.h #include semaphore.h #define MAXLON 1000 int cuenta blancos= 0; sem t blancos; typedef struct { char∗ nombre; int cont; } info; 79 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 80 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 82. void ∗cuenta (void ∗dato) { int pos, cont= 0, leidos; info ∗misdatos= (info ∗) dato; char cadena[MAXLON]; int fd; fd= open (misdatos-nombre, O RDONLY); while ((leidos= read (fd, cadena, MAXLON))!= 0) for (pos= 0; pos leidos; pos++) if (cadena[pos]==’ ’) cont++; misdatos-cont= cont; sem wait (blancos); cuenta blancos+= cont; sem post (blancos); close (fd); pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t hilo[argc-1]; info datos[argc-1]; int numfich; if (argc 2) { printf (Indica el nombre de uno o varios ficheros.n); exit(0); } @ibaumo sem init (blancos, 0, 1); for (numfich= 0; numfich argc-1; numfich++) { datos[numfich].nombre= argv[numfich+1]; datos[numfich].cont= 0; pthread create (hilo[numfich], NULL, cuenta, (void ∗) datos[numfich]); } for (numfich= 0; numfich argc-1; numfich++) pthread join (hilo[numfich], NULL); for (numfich= 0; numfich argc-1; numfich++) printf (Fichero %s: %d espacios en blanco encontradosn, datos[numfich].nombre, datos[numfich].cont); printf (Total de espacios en blanco: %dn, cuenta blancos); sem destroy (blancos); return 0; } 45. #include stdio.h #include stdlib.h #include time.h #include unistd.h #include pthread.h #include semaphore.h sem t s1, s2, s3, s4, s5, s6; 80 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 81 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 83. void escribe (char ∗dato) { int num; for(num= 0; num 5; num++){ printf ( %sn,dato); fflush (stdout); sleep (random() %3); } } void ∗A (void ∗p){ escribe (a1); sem post (s1); sem wait (s2); escribe (a2); sem post (s4); sem wait (s5); escribe (a3); sem post (s6); pthread exit (NULL); } void ∗B (void ∗p){ escribe ( b1); sem post (s2); escribe ( b2); sem post (s3); @ibaumo sem wait (s4); escribe ( b3); sem wait (s6); sem wait (s6); escribe ( b4); pthread exit (NULL); } void ∗C (void ∗p){ sem wait (s1); escribe ( c1); sem wait (s3); escribe ( c2); sem post (s5); escribe ( c3); sem post (s6); pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t th1, th2, th3; sem init (s1, 0, 0); sem init (s2, 0, 0); sem init (s3, 0, 0); sem init (s4, 0, 0); sem init (s5, 0, 0); sem init (s6, 0, 0); pthread create (th1, NULL, A, NULL); 81 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 82 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 84. pthread create (th2, NULL, B, NULL); pthread create (th3, NULL, C, NULL); pthread join (th1, NULL); pthread join (th2, NULL); pthread join (th3, NULL); sem destroy (s1); sem destroy (s2); sem destroy (s3); sem destroy (s4); sem destroy (s5); sem destroy (s6); return 0; } 46. #include stdio.h #include stdlib.h #include time.h #include unistd.h #include pthread.h #include semaphore.h #define MAX 6 sem t A, B, C; void ∗escribirA (void ∗nada){ int num; @ibaumo for (num= 0; num MAX; num++){ sem wait (A); printf (A); fflush (stdout); sem post (B); sleep (random() %3); } pthread exit (NULL); } void ∗escribirB (void ∗nada){ int num; for (num= 0; num MAX; num++){ sem wait (B); printf (B); fflush (stdout); sem post (C); sleep (random() %2); } pthread exit (NULL); } void ∗escribirC (void ∗nada){ int num; for (num= 0; num MAX; num++){ sem wait (C); printf (C); 82 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 83 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 85. fflush (stdout); sem post (A); sleep (random() %2); } pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t th1, th2, th3; srandom(time(NULL)); sem init (A, 0, 1); /∗ habilitado ∗/ sem init (B, 0, 0); /∗ no habilitado ∗/ sem init (C, 0, 0); /∗ no habilitado ∗/ pthread create (th1, NULL, escribirA, NULL); pthread create (th2, NULL, escribirB, NULL); pthread create (th3, NULL, escribirC, NULL); pthread join (th1, NULL); pthread join (th2, NULL); pthread join (th3, NULL); sem destroy (A); sem destroy (B); sem destroy (C); return 0; } 47. Estos son los posibles valores de num as´ como los diferentes estados de los ı hilos: @ibaumo num es 13, incementa termina, decrementa se bloquea en sem wait(sem2) con i a cero. num es 12, incrementa termina, decrementa se bloquea en sem wait(sem2) con i a uno. num es 11, incrementa termina, decrementa se bloquea en sem wait(sem2) con i a dos. num es 10, incrementa termina, decrementa se bloquea en sem wait(sem1) a continuaci´ n del bucle. o 48. Utilizando dos sem´ foros, sA y sB, con sA a cero y sB a uno, esta es la a soluci´ n: o void *escribirA (void *p) { void *escribirB (void *p) { int i; int i; for (i= 0; i 5; i++) { for (i= 0;i 5; i++) { sem_wait(sA); sem_wait(sB); printf (A); printf (B); fflush(NULL); fflush(NULL); sleep(random()%2); sleep(random()%2); sem_post(sB); sem_post(sA); } } pthread_exit(NULL); pthread_exit(NULL); } } 49. Los tres hilos se van a quedar bloqueados: 83 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 84 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 86. escribirA queda bloqueado en el sem wait(s1) con i = 2. escribirB queda bloqueado en el primer sem wait(s2) con j = 2. escribirC queda bloqueado en el primer sem wait(s3) con k = 1. 50. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include stdbool.h #define MAX 10 #define FIN -1 int buffer[MAX]; sem t huecos, elementos; int generar dato (void) { return random() %256;} int numero aleatorio(void) { return random() %100;} void ∗productor (void ∗p) { int pos productor= 0; int num, dato, n; n= numero aleatorio(); printf (Productor con %d datosn, n); for(num= 0; num n; num++) { @ibaumo dato= generar dato(); sem wait (huecos); buffer[pos productor]= dato; pos productor= (pos productor+ 1) %MAX; sem post (elementos); } sem wait (huecos); buffer[pos productor]= FIN; sem post (elementos); pthread exit (NULL); } void ∗consumidor(void ∗p){ int pos consumidor= 0, dato; bool continuar= true; while (continuar) { sem wait (elementos); dato= buffer[pos consumidor]; sem post (huecos); if (dato== FIN) continuar= false; else { printf (Numero aleatorio: %dn, dato); pos consumidor= (pos consumidor+1) %MAX; } } pthread exit (NULL); } 84 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 85 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 87. int main (int argc, char ∗argv[]) { pthread t hiloproductor, hiloconsumidor; sem init (elementos, 0, 0); sem init (huecos, 0, MAX); pthread create (hiloproductor, NULL, productor, NULL); pthread create (hiloconsumidor, NULL, consumidor, NULL); pthread join (hiloproductor, NULL); pthread join (hiloconsumidor, NULL); sem destroy (huecos); sem destroy (elementos); return 0; } 51. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include stdbool.h #define MAX 10 #define FIN -1 #define NUMPROD 3 @ibaumo int buffer[MAX]; int pos productor= 0; sem t huecos, elementos, pos prod; int generar dato (void) { return random() %256;} int numero aleatorio (void) { return random() %100;} void ∗productor (void ∗p) { int num, dato, n; n= numero aleatorio(); for(num= 0; num n; num++) { dato= generar dato(); sem wait (huecos); sem wait (pos prod); buffer[pos productor]= dato; pos productor= (pos productor+ 1) %MAX; sem post (pos prod); sem post (elementos); } sem wait (huecos); sem wait (pos prod); buffer[pos productor]= FIN; pos productor= (pos productor+ 1) %MAX; sem post (pos prod); sem post (elementos); pthread exit (NULL); } 85 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 86 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 88. void ∗consumidor(void ∗p){ int pos consumidor= 0, dato, cont fin= 0; bool continuar= true; while (continuar) { sem wait (elementos); dato= buffer[pos consumidor]; sem post (huecos); pos consumidor= (pos consumidor+1) %MAX; if (dato== FIN) { cont fin++; if (cont fin== NUMPROD) continuar= false; } else printf (Numero aleatorio: %dn, dato); } pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t hiloconsumidor, hiloproductor[NUMPROD]; int num; sem init (elementos, 0, 0); sem init (huecos, 0, MAX); sem init (pos prod, 0, 1); @ibaumo for (num= 0; num NUMPROD; num++) pthread create (hiloproductor[num], NULL, productor, NULL); pthread create (hiloconsumidor, NULL, consumidor, NULL); for (num= 0; num NUMPROD; num++) pthread join (hiloproductor[num], NULL); pthread join (hiloconsumidor, NULL); sem destroy (huecos); sem destroy (elementos); sem destroy (pos prod); return 0; } 52. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include math.h #include stdbool.h #define MAX 5 #define FIN -1 int buffer[MAX]; sem t huecos,elementos; int inicio, fin; 86 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 87 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 89. /∗ Devuelve la suma de los d´gitos del n´mero dado ∗/ ı u int suma digitos (int numero) { int suma= 0; while (numero 0) { suma+= numero %10; numero/= 10; } return suma; } /∗ Indica si el n´mero dado es primo ∗/ u bool es primo (int numero) { int divisor; for (divisor= 2; divisor= sqrt(numero); divisor++) if (numero %divisor== 0) return false; return true; } void ∗productor (void ∗param) { int pos productor=0; int num; @ibaumo for (num= inicio; num fin; num++) if (es primo (num)) { sem wait (huecos); buffer[pos productor]= num; pos productor= (pos productor+1) %MAX; sem post (elementos); } sem wait (huecos); buffer[pos productor]= FIN; sem post (elementos); pthread exit(NULL); } void ∗consumidor (void ∗param) { int pos consumidor=0; int dato; bool fin= false; while (!fin) { sem wait (elementos); dato= buffer[pos consumidor]; pos consumidor= (pos consumidor+1) %MAX; sem post (huecos); if (dato== FIN) fin= true; else printf (N´ mero primo: %d; Suma de los digitos: %dn, u dato, suma digitos(dato)); } 87 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 88 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 90. pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t hiloproductor, hiloconsumidor; if (argc!= 3) { printf (Indica los dos n´ meros enteros.n); u exit (0); } inicio= atoi (argv[1]); fin= atoi (argv[2]); sem init (huecos, 0, MAX); sem init (elementos, 0, 0); pthread create (hiloproductor, NULL, productor, NULL); pthread create (hiloconsumidor, NULL, consumidor, NULL); pthread join (hiloproductor, NULL); pthread join (hiloconsumidor, NULL); sem destroy (huecos); sem destroy (elementos); return 0; } @ibaumo 53. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include stdbool.h #define MAXALU 25 #define MAXRES 4 #define RANGO 12 #define LIBRE -1 #define HORAINICIO 9 sem t sem tabla, sem consultas; int tabla[RANGO], consultas=0; void consulta (int id) { int num; sem wait (sem consultas); consultas++; if (consultas== 1) sem wait(sem tabla); sem post (sem consultas); for (num= 0; num RANGO; num++) if (tabla[num]!= LIBRE) printf (Consulta de %d: %d- %d ¡=¿ %dn, id, num+HORAINICIO, num+HORAINICIO+1, tabla[num]); else 88 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 89 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 91. printf (Consulta de %d: %d- %d ¡=¿ LIBREn, id, num+HORAINICIO, num+HORAINICIO+1); sem wait (sem consultas); consultas--; if (consultas== 0) sem post (sem tabla); sem post (sem consultas); pthread exit (NULL); } void reserva (int hora, int id) { printf (Solicitud de reserva de %d; %d- %dn, id, hora, hora+1); sem wait (sem tabla); if (tabla[hora-HORAINICIO]!= LIBRE) printf (Denegada reserva de %d: %d- %d est´ ocupadan, id, hora, hora+1); a else { tabla[hora-HORAINICIO]= id; printf (Reserva de %d: %d- %dn, id, hora, hora+1); } sem post (sem tabla); } void cancela (int id) { int num; bool hay= false; @ibaumo printf (Solicitud de cancelaci´ n de %dn, id); o sem wait (sem tabla); for (num= 0; num RANGO; num++) { if (tabla[num]== id) { hay= true; tabla[num]= LIBRE; printf (Cancelaci´ n de %d: %d- %dn, id, o num+HORAINICIO, num+HORAINICIO+1); } } if (hay== false) printf (Denegada cancelaci´ n de %d: No tiene reservasn, id); o sem post (sem tabla); } void ∗alumno (void ∗dato) { int id= ∗(int ∗)dato, num, prob; for (num= 0; num MAXRES; num++) { prob= random() %100; if (prob 50) reserva (random() %RANGO+HORAINICIO, id); else if (prob 75) cancela (id); else consulta (id); } pthread exit (NULL); } 89 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 90 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 92. int main (int argc, char ∗argv[]) { pthread t hilos[MAXALU]; int num, dato[MAXALU]; sem init (sem tabla, 0, 1); sem init (sem consultas, 0, 1); for (num= 0; num RANGO; num++) tabla[num]= LIBRE; for (num= 0; num MAXALU; num++) { sleep (random() %3); /∗ simula una espera aleatoria ∗/ dato[num]= num; pthread create (hilos[num], NULL, alumno, (void ∗)dato[num]); } for (num= 0; num MAXALU; num++) pthread join (hilos[num], NULL); sem destroy (sem tabla); sem destroy (sem consultas); return 0; } 54. #include stdio.h #include stdlib.h #include semaphore.h @ibaumo #include pthread.h #include unistd.h #define MAX 100 int ncochesDirB= 0, ncochesDirA= 0; sem t puente, dirB, dirA; void ∗direccionB (void ∗dato) { int id= (int) dato; sleep (random() %20); sem wait (dirB); ncochesDirB++; if (ncochesDirB== 1) sem wait (puente); printf (Entra en puente Dir B coche %dn, id); sem post (dirB); sleep (1); /∗ cruzar el puente ∗/ sem wait (dirB); ncochesDirB--; printf (Sale del puente Dir B coche %dn, id); if (ncochesDirB== 0) sem post (puente); sem post (dirB); pthread exit (NULL); } 90 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 91 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 93. void ∗direccionA (void ∗dato) { int id= (int) dato; sleep (random() %20); sem wait (dirA); ncochesDirA++; if (ncochesDirA== 1) sem wait (puente); printf (Entra en puente Dir A coche %dn, id); sem post (dirA); sleep (1); /∗ cruzar el puente ∗/ sem wait (dirA); ncochesDirA--; printf (Sale del puente Dir A coche %dn, id); if (ncochesDirA== 0) sem post (puente); sem post (dirA); pthread exit (NULL); } int main (int argc, char ∗argv[]) { pthread t hilos[MAX]; int num; @ibaumo sem init (dirA, 0, 1); sem init (dirB, 0, 1); sem init (puente, 0, 1); for (num= 0; num MAX; num+= 2) { sleep (random() %3); pthread create (hilos[num], NULL,direccionB,(void∗)num); pthread create (hilos[num+1],NULL,direccionA,(void∗)(num+1)); } for (num= 0; num MAX; num++) pthread join (hilos[num], NULL); sem destroy (dirA); sem destroy (dirB); sem destroy (puente); return 0; } 55. En primer lugar se calcula lo que ocupa la FAT, que es el tama˜ o del enlace n (32 bits) por el n´ mero de entradas de la tabla que, a su vez, es el tama˜ o del u n disco dividido por el tama˜ o del agrupamiento y que en este problema son n 20GB/(16 ∗ 512bytes) = 20 ∗ 217 entradas. Luego la tabla ocupa 20 ∗ 217 ∗ 32bits = 20 ∗ 219 bytes. Si se divide lo que ocupa la tabla por el tama˜ o del agrupamiento se obtiene n el n´ mero de agrupamientos que ocupa la tabla: 20 ∗ 219 /(16 ∗ 512) = 20 ∗ u 91 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 92 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 94. 26 = 1280 agrupamientos, que multiplicado por 16, que es el n´ mero de u sectores por agrupamiento, se obtiene el n´ mero total de sectores que es u 20480. 56. En un sistema de archivos FAT, los bloques se asignan como una lista en- lazada que finaliza con la posici´ n fin de lista EOF. Es posible recuperar o datos utilizando los enlaces partiendo desde esa posici´ n EOF hacia atr´ s. o a La reconstrucci´ n de la lista de bloques ser´ : o a 14 → 15 → 12 → 13 → 10 → 11 → EOF La informaci´ n de esa lista de bloques ser´ : o a sigan → buscando → yo → no → he → sido → EOF 57. Se trata de un sistema de archivos FAT en el que un fichero de 160KB ocu- pa 10 entradas. Como cada sector de disco contiene 512 bytes, el fichero ocupa 160 KB / 512 bytes = 320 sectores. Como dicho fichero ocupa 10 en- tradas, entonces cada agrupamiento estar´ compuesto por 32 sectores como a m´nimo. ı @ibaumo 58. Como el sistema es FAT16 puede direccionar un total de 216 bloques * 1KB = 64MB. Si la partici´ n es de 2GB, el tama˜ o de bloque deber´a ser como m´nimo o n ı ı el resultado de dividir el tama˜ o de la partici´ n entre el n´ mero m´ ximo de n o u a bloques, es decir, 2GB/2 16 bloques = 32KB por bloque. 59. El m´ ximo ser´ el n´ mero de entradas de la FAT por el tama˜ o del bloque, a a u n es decir, 2 16 ∗ 4KB = 256M B. Si la partici´ n es de 8GB, no es adecuado el tama˜ o de bloque ya que s´ lo o n o utilizar´a 256MB de esos 8GB. ı El tama˜ o de bloque adecuado se puede obtener dividiendo el tama˜ o de la n n partici´ n entre el n´ mero de ´ndices de la FAT, es decir, 8GB/2 o u ı 16 = 128KB por bloque. Para saber cu´ ntos bloques ocupa la FAT, calculamos el tama˜ o de esta que a n es 216 ∗2bytes = 128KB, el cual coincide con el tama˜ o de justo un bloque. n 60. En un sistema FAT16 tenemos 216 posibles ´ndices. Por lo tanto, el espa- ı cio m´ ximo es el n´ mero de ´ndices por el tama˜ o del bloque, es decir, a u ı n 216 ∗ 1KB = 64M B. Como la partici´ n es de 8GB, entonces el espacio o inutilizado es la diferencia, es decir, 8GB − 64M B. En el caso del sistema de ficheros basado en nodos-i, el n´ mero de enlaces u que caben en un bloque se calcula dividiendo el tama˜ o del bloque por el n 92 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 93 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 95. tama˜ o del enlace, es decir, 1KB/16Bytes = 64 enlaces por bloque. Co- n mo el fichero ocupa 131KB, se utilizar´ n los dos ´ndices directos (con los a ı que se direcciona un total de 2KB), los dos indirectos simples (con los que se direcciona un total de 128KB) y el primer ´ndice indirecto doble (para ı direccionar el bloque de datos que falta). Si el bloque no legible es un bloque de datos s´ lo se perder´a dicho bloque, o ı es decir, 1KB. Sin embargo, en el caso de no poder leer un bloque de enlaces, si se trata del bloque apuntado por el ´ndice indirecto simple, se perder´an 64 ı ı bloques de datos. Si se trata de uno de los dos bloques de ´ndices utilizados ı por el ´ndice indirecto doble, se perder´ un s´ lo bloque de datos. ı a o 61. Si el fichero tiene 1548 KB, y en cada bloque caben 2KB, utiliza 1548KB / 2KB = 774 bloques de datos. Los cinco ´ndices directos del nodo-i permiten acceder a cinco bloques de ı datos, y no se utilizan bloques para almacenar enlaces, por lo que quedan por indexar 769 bloques de datos. Cada ´ndice indirecto simple permite indexar 256 bloques de datos ya que si ı el tama˜ o de bloque son 2KB y cada ´ndice ocupa 64 bits, es decir, 8 bytes, n ı tenemos que 2KB / 8bytes = 256 ´ndices. Al mismo tiempo, cada ´ndice ı ı indirecto simple consume un bloque para almacenar enlaces. @ibaumo Con los tres enlaces indirectos simples que tiene el nodo-i, indexamos 3*256= 768 bloques de datos del fichero, consume 3 bloques para almacenar enlaces, y a´ n queda un bloque de datos del fichero por indexar. u Para indexar el bloque de datos que falta, se utilizar´ el primer ´ndice indi- a ı recto doble, que utilizar´ 2 bloques para almacenar enlaces (el m´nimo para a ı indexar un bloque). As´, en total, se utilizan 3 + 2 = 5 bloques para almacenar enlaces. ı 62. El n´ mero de ´ndices que caben en un bloque se obtiene dividiendo el tama˜ o u ı n del bloque entre el tama˜ o del ´ndice, es decir, 4KB/32bits= 1024 ´ndices. n ı ı Los ´ndices directos del nodo-i no consumen bloques de ´ndices. Cada ´ndice ı ı ı indirecto simple consume un bloque de ´ndices, y cada ´ndice indirecto doble ı ı consume 1+1024 bloques de ´ndices. Si el fichero ocupa el m´ ximo tama˜ o ı a n posible, el n´ mero de bloques que contendr´ n ´ndices para ese fichero ser´ : u a ı a 2 + 1 + 1024 bloques. 63. void listado(char nomdir[]) { DIR ∗d; struct dirent ∗entrada; char ∗ruta; struct stat datos, datos l; d= opendir(nomdir); if (d== NULL) printf(Error al abrir el directorion); 93 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 94 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 96. else { entrada= readdir(d); while (entrada!= NULL) { ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2); sprintf(ruta, %s/ %s, nomdir, entrada-d name); stat (ruta,datos); lstat(ruta,datos l); if(S ISDIR(datos.st mode) S ISLNK(datos l.st mode)) printf( %sn, ruta); free(ruta); entrada= readdir(d); } closedir(d); } } 64. void listado(char nomdir[]) { DIR ∗d; struct dirent ∗entrada; char ∗ruta, ∗ruta zip; struct stat datos, datos zip; d= opendir(nomdir); if (d== NULL) printf(Error al abrir el directorion); else { entrada= readdir(d); while (entrada!= NULL) { ruta= malloc(strlen(nomdir)+strlen(entrada-d name)+2); @ibaumo sprintf(ruta, %s/ %s, nomdir, entrada-d name); lstat(ruta,datos); if(S ISREG(datos.st mode)){ ruta zip= malloc(strlen(entrada-d name)+10); sprintf(ruta zip,/tmp/ %s.zip, entrada-d name); if (fork()== 0) execlp(zip, zip, ruta zip, ruta, NULL); else { wait(NULL); stat(ruta zip, datos zip); printf(Datos %ldn, datos.st size - datos zip.st size); } free(ruta zip); } free(ruta); entrada= readdir(d); } closedir(d); } } 65. #include stdio.h #include stdlib.h #include sys/stat.h #include unistd.h #include dirent.h #include string.h int main (int argc, char ∗argv[]) { DIR ∗dir; 94 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 95 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 97. struct dirent ∗entrada; struct stat datos; char ∗ ruta; if (argc!= 2) { printf (Debe especificar un directorion); exit (1); } else printf (El directorio especificado existe y es accesiblen); dir= opendir(argv[1]); if (dir== NULL) { printf (El directorio especificado no existe o no tienes permisos.n); exit (1); } entrada= readdir(dir); while (entrada!= NULL) { ruta= malloc(strlen (argv[1])+ strlen (entrada-d name)+ 2); sprintf (ruta, %s/ %s, argv[1], entrada-d name); lstat (ruta, datos); if (S ISDIR (datos.st mode)) if (rmdir (ruta)== 0) printf ( %s se ha borradon, ruta); else printf ( %s NO se ha borradon, ruta); else if (unlink (ruta)== 0) printf ( %s se ha borradon, ruta); else @ibaumo printf ( %s NO se ha borradon, ruta); free (ruta); entrada= readdir(dir); } closedir(dir); return 0; } 66. #include stdio.h #include stdlib.h #include time.h #include sys/stat.h #include unistd.h int main(int argc, char ∗argv[]) { struct stat datos; int num; if (argc 2) { printf (Debe especificar al menos un fichero o directorion); exit (1); } for (num= 1; num argc; num++) { if (lstat (argv[num], datos)!= 0) { printf (Error al ejecutar stat, %s no existen, argv[num]); } else { if (S ISREG (datos.st mode)) { printf ( %s es un ficheron, argv[num]); 95 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 96 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 98. if (unlink (argv[num])== 0) { printf ( %s se ha borradon, argv[num]); if (datos.st nlink 1) printf (Pero no se han liberado bloquesn); else printf (Se han liberado %d bloquesn, (int)datos.st blocks); } else printf ( %s NO se ha borradon, argv[num]); } else { if (S ISLNK (datos.st mode)) { printf ( %s es un enlace simbolicon, argv[num]); if (unlink (argv[num])== 0) printf ( %s se ha borrado y se han liberado %d bloquesn, argv[num], (int)datos.st blocks); else printf ( %s NO se ha borradon, argv[num]); } else { if (S ISDIR (datos.st mode)) { printf ( %s es un directorion, argv[num]); if (rmdir (argv[num])== 0) printf ( %s se ha borrado y se han liberado %d bloquesn, argv[num], (int)datos.st blocks); else printf ( %s NO se ha borradon, argv[num]); } } } } } return 0; @ibaumo } 67. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include string.h #include time.h void recorre (char ∗nombredir) { DIR ∗dir; struct dirent ∗entrada; struct stat datos; char ∗ruta; dir= opendir(nombredir); if (dir== NULL) { printf (Error al abrir el directorio %sn, nombredir); return; } entrada= readdir(dir); while (entrada!= NULL) { if (strcmp (entrada-d name,.) strcmp (entrada-d name,..)) { ruta= malloc (strlen (nombredir)+ strlen (entrada-d name)+ 2); sprintf (ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta, datos); if (S ISDIR (datos.st mode)) 96 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 97 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 99. recorre (ruta); /∗ recorrido recursivo ∗/ else if (S ISREG (datos.st mode) (datos.st uid== getuid()) (time(NULL)-datos.st atime 60∗60)) printf ( %sn,ruta); free (ruta); } entrada= readdir(dir); } closedir (dir); } int main (int argc, char ∗argv[]) { if (argc!= 2) printf(Debe especificar un directorion); else recorre (argv[1]); return 0; } 68. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include stdbool.h #include sys/types.h @ibaumo #include sys/wait.h #include string.h int total= 0, longitud= 0, ∗nodos i= NULL; void anyade (int nodo i) { if (longitud %10== 0) nodos i= (int ∗) realloc (nodos i, (longitud+10)∗ sizeof (int)); nodos i[longitud]= nodo i; longitud++; } bool esta(int nodo i) { int num; for (num= 0; num longitud; num++) if (nodos i[num]== nodo i) return true; return false; } void recorre (char ∗nombredir) { DIR ∗dir; struct dirent ∗entrada; struct stat datos; char ∗ruta; dir= opendir(nombredir); 97 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 98 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 100. if (dir== NULL) { printf (Error al abrir el directorio %sn, nombredir); return; } entrada= readdir(dir); while (entrada!= NULL) { if (strcmp(entrada-d name,.) strcmp(entrada-d name,..)) { ruta= malloc(strlen (nombredir)+ strlen(entrada-d name)+ 2); sprintf (ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta, datos); if (S ISDIR (datos.st mode)) recorre (ruta); /∗ llamada recursiva ∗/ total+= datos.st size; if (datos.st nlink 1) { if (esta (datos.st ino)== false) anyade (datos.st ino); else total-= datos.st size; /∗ repetido ∗/ } free (ruta); } entrada= readdir (dir); } closedir (dir); } int main(int argc, char ∗argv[]) { if (argc!= 2) { @ibaumo printf (Debe especificar un directorion); exit (1); } recorre (argv[1]); printf (Total en bytes: %dn, total); return 0; } 69. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include string.h #include time.h void recorre (char ∗nombredir, char ∗nombrefile, int nodo i) { DIR ∗dir; struct dirent ∗entrada; struct stat datos; char ∗ruta; dir= opendir(nombredir); if (dir== NULL) { printf (Error al abrir el directorio %sn, nombredir); return; } 98 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 99 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 101. entrada= readdir(dir); while (entrada!= NULL) { if (strcmp (entrada-d name,.) strcmp (entrada-d name,..)) { ruta= malloc (strlen (nombredir)+ strlen (entrada-d name)+ 2); sprintf (ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta, datos); if (S ISDIR (datos.st mode)) recorre (ruta, nombrefile, nodo i); /∗ llamada recursiva ∗/ else if (S ISREG (datos.st mode) (strcmp (ruta, nombrefile)!= 0) (datos.st ino== nodo i)) { unlink (ruta); symlink (nombrefile, ruta); } free (ruta); } entrada= readdir (dir); } closedir (dir); } int main (int argc, char ∗argv[]) { struct stat datos; if (argc!= 3) printf(Debe especificar un fichero y un directorion); else { lstat (argv[1], datos); @ibaumo if (datos.st nlink 1) recorre (argv[2], argv[1], datos.st ino); } return 0; } 70. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include string.h #include stdbool.h bool tiene extension (char ext[], char nombre[]) { return (!strcmp(ext, nombre[strlen(nombre)-strlen(ext)])); } void crear enlace (char ruta[], char nombre entrada[], char ext[]) { char ∗ruta2; struct stat datos; ruta2= (char ∗) malloc(strlen(/resultado/)+ strlen(ext)+ strlen(nombre entrada)+2); sprintf (ruta2, /resultado/ %s/ %s, ext, nombre entrada); if (lstat (ruta2, datos)!= 0) /∗ no existe enlace simbolico ∗/ symlink (ruta, ruta2); free (ruta2); } 99 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 100 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 102. void recorre(char ∗nombredir) { DIR ∗dir; struct dirent ∗entrada; struct stat datos; char ∗ruta; dir= opendir(nombredir); if (dir== NULL) { printf (Error al abrir el directorio %sn, nombredir); return; } entrada= readdir(dir); while (entrada!= NULL) { if (strcmp (entrada-d name,.) strcmp (entrada-d name,..)) { ruta= (char∗) malloc (strlen (nombredir)+ strlen (entrada-d name)+ 2); sprintf (ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta, datos); if (S ISDIR (datos.st mode)) recorre (ruta); else if (S ISREG (datos.st mode)) { if (tiene extension (.jpeg, entrada-d name)) crear enlace (ruta, entrada-d name, jpeg); else if (tiene extension (.mp3, entrada-d name)) crear enlace (ruta, entrada-d name, mp3); @ibaumo else if (tiene extension (.avi, entrada-d name)) crear enlace (ruta, entrada-d name, avi); } free (ruta); } entrada= readdir (dir); } closedir (dir); } int main (int argc, char ∗argv[]) { recorre(/media); return 0; } 71. Si 1GB es el m´ ximo de memoria que se puede direccionar, la direcci´ n a o l´ gica consta de 30 bits. Como el tama˜ o de p´ gina es de 16KB, de los 30 o n a bits de la direcci´ n l´ gica, 14 bits se utilizan para direccionar el contenido de o o la p´ gina, y el resto, 16, para direccionar las p´ ginas, por lo que el n´ mero a a u total de p´ ginas que un proceso puede tener asignadas es de 2 a 16 . Si la tabla de primer nivel contiene 1024 entradas, esto implica que su codifi- caci´ n consume 10 bits en la direcci´ n l´ gica, por lo que quedan 6 bits para o o o la tabla de segundo nivel, lo que permite direccionar 26 p´ ginas, es decir, a 64 p´ ginas. Como el proceso requiere 6401 p´ ginas, se obtiene que necesita a a 101 tablas de segundo nivel. 100 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 101 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 103. 72. Si el tama˜ o de p´ gina son 2KB, esto implica que de los 22 bits de la direc- n a ci´ n l´ gica, 11 bits se utilizan para direccionar la p´ gina, por lo que quedan o o a 11 bits para codificar la tabla de p´ ginas. a Si se utiliza una tabla de p´ ginas de un s´ lo nivel, su tama˜ o es el n´ mero a o n u de entradas de la tabla por el tama˜ o de la entrada, es decir, 211 ∗ 8 = 214 n bytes. Si se utiliza una tabla de p´ ginas de dos niveles, 6 bits de la direcci´ n l´ gica a o o se emplean para el primer nivel ya que el enunciado dice que 5 bits son para el segundo nivel. Entonces, cada tabla de segundo nivel direcciona hasta 25 p´ ginas, es decir 32 p´ ginas de 2KB cada una (total 64KB). Como el proceso a a requiere 90KB, hacen falta 2 tablas de segundo nivel. As´, el consumo es ı el de una tabla de primer nivel m´ s el de dos de segundo nivel, esto es, a 2 6 ∗ 8 + 2 ∗ 25 ∗ 8 = 210 bytes. Por lo tanto, el ahorro al utilizar una tabla de p´ ginas de dos niveles es de a 214 − 210 bytes. 73. Como el tama˜ o de la p´ gina es de 4 KB, de los 20 bits de direcci´ n l´ gica, n a o o 12 bits son para direccionar el contenido de la p´ gina y, por lo tanto, 8 bits a son para direccionar las p´ ginas. a Si el sistema tiene una tabla de un solo nivel, la tabla tiene 256 entradas, y su coste de almacenamiento es de 256 ∗ 16 = 212 bytes. @ibaumo Si el sistema tiene una tabla de dos niveles, la tabla de primer nivel tiene 24 entradas, 16 entradas, al igual que la de segundo nivel. Si un proceso utiliza 192 KB, se obtiene que necesita 192KB/4KB = 48 p´ ginas, y se emplean a 3 tablas de segundo nivel. Ahora el consumo es de una tabla de primer nivel y 3 de segundo, es decir, 24 ∗ 16 + 3 ∗ 24 ∗ 16 = 210 bytes. Por lo tanto, el ahorro es 212 − 210 bytes. 74. Si el tama˜ o de p´ gina son 2KB, esto implica que de los 22 bits de la direc- n a ci´ n l´ gica, 11 bits se utilizan para direccionar la p´ gina, por lo que quedan o o a 11 bits para codificar la tabla de p´ ginas. Por lo tanto, el n´ mero m´ ximo de a u a p´ ginas que puede tener asignado un proceso es 211 p´ ginas. a a Con una tabla de p´ ginas de dos niveles, la tabla de primer nivel tiene 23 a entradas, y la de segundo nivel tiene 28 entradas, es decir, 256 entradas. Por lo que si un proceso utiliza 1000 p´ ginas, entonces son necesarias 4 tablas a de segundo nivel. 75. En general, utilizar tablas de p´ ginas de dos niveles suele producir un ahorro a en el consumo de memoria comparado con utilizar una tabla de un solo nivel. Sin embargo, en el caso de que el proceso requiriera, por ejemplo, la totalidad del espacio de memoria, ya no ser´a cierto. ı Por ejemplo, suponer que se disponen de 4 bits para direccionar p´ ginas, a donde en un sistema de paginaci´ n de 2 niveles, 2 bits son para el primer o 101 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 102 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 104. nivel y 2 bits son para el segundo nivel. En una tabla de un solo nivel hay entonces 16 entradas. En una tabla de dos niveles, hay 4 entradas para la tabla de primer nivel y, por lo tanto, cuatro tablas de segundo nivel donde cada una de estas tablas consta de 4 entradas. Si cada entrada a la tabla de p´ ginas requiere n bytes, el coste de almacenar la tabla de p´ ginas de un a a nivel es 16 ∗ n bytes, que es menor que el coste de almacenar la tabla de p´ ginas de dos niveles que es (4 + 4 ∗ 4) ∗ n bytes. Por lo tanto, en este caso a la tabla de p´ ginas de dos niveles consume m´ s memoria que la de un nivel. a a Respecto al segundo punto, la afirmaci´ n no es correcta. El n´ mero de p´ gi- o u a nas que se pueden asignar a un proceso es independiente de si el sistema de paginaci´ n utiliza un nivel o m´ s, ya que en verdad depende del n´ mero o a u de bits de la direcci´ n l´ gica que se utilizan para direccionar las p´ ginas. o o a Siguiendo con el ejemplo anterior, ese n´ mero de bits es 4, y el n´ mero u u m´ ximo de p´ ginas es por lo tanto de 16. a a 76. Si se direcciona 1GB (230 bytes), entonces la direcci´ n l´ gica es de 30 bits. o o Si la p´ gina es de 32KB (2 a 15 bytes), y cada palabra son 2 bytes, har´ n falta a 14 bits para direccionar el contenido de una p´ gina. En consecuencia, quedan a 16 bits de la direcci´ n l´ gica para la tabla de p´ ginas. Si el proceso requiere o o a ´ 90MB, necesita 90MB/32KB = 2880 p´ ginas. Si se utiliza una unica tabla de a p´ ginas, el consumo de memoria ser´ el tama˜ o de la tabla por el tama˜ o de a a n n @ibaumo la entrada, es decir, 2 16 ∗ 16 = 220 bytes. Si se utiliza una tabla de p´ ginas a de dos niveles, donde 8 bits son para el primer nivel y otros 8 bits para el segundo, el proceso utilizar´ la tabla de primer nivel m´ s 12 de segundo, ya a a que cada tabla de segundo nivel apunta a 256 p´ ginas y el proceso requiere a un total de 2880. El consumo en este caso es de 28 ∗ 16 + 12 ∗ 28 ∗ 16 = 13 ∗ 212 bytes, y el ahorro es la diferencia de los costes obtenidos, es decir, 220 − 13 ∗ 212 bytes. 77. El sistema requiere 12 bits para direccionar el contenido de una p´ gina ya a que la p´ gina es de 32KB (2 a 15 bytes) y el tama˜ o de la palabra es de 64 bits n (2 3 bytes). Quedan 18 bits para la tabla de p´ ginas. a Si el proceso requiere 256MB, entonces 256M B/32KB = 213 es el n´ mero u de p´ ginas. En el caso de la tabla de p´ ginas de dos niveles, se utilizan 9 bits a a para el primer nivel y otros tantos para el segundo. Por lo que el proceso requiere 213 /29 = 24 tablas de segundo nivel. As´, el ahorro de memoria ı ser´ la diferencia entre los consumos de ambas representaciones, es decir, a 218 ∗ 8 − (29 + 24 ∗ 29 ) ∗ 8 bytes. 78. Con 3 marcos: FIFO: 10 fallos de p´ gina a • P´ gina 0: 2 → 4 → 3 → 6 a • P´ gina 1: 3 → 5 → 1 a 102 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 103 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 105. • P´ gina 2: 1 → 2 → 5 a LRU: 9 fallos de p´ gina a • P´ gina 0: 2 → 5 a • P´ gina 1: 3 → 4 → 3 → 6 a • P´ gina 2: 1 → 5 → 1 a Con 4 marcos: FIFO: 9 fallos de p´ gina a • P´ gina 0: 2 → 5 → 6 a • P´ gina 1: 3 → 2 a • P´ gina 2: 1 → 3 a • P´ gina 3: 4 → 1 a LRU: 8 fallos de p´ gina a • P´ gina 0: 2 → 6 a • P´ gina 1: 3 → 5 a • P´ gina 2: 1 → 3 a • P´ gina 3: 4 → 1 a Para ambas pol´ticas se reduce el n´ mero de fallos de p´ gina al aumentar el ı u a @ibaumo n´ mero de marcos a 4. u 79. FIFO: 8 fallos de p´ gina a • P´ gina 0: 4 → 3 a • P´ gina 1: 2 → 5 a • P´ gina 2: 1 → 4 a • P´ gina 3: 6 → 1 a LRU: 11 fallos de p´ gina a • P´ gina 0: 4 → 2 → 1 a • P´ gina 1: 2 → 3 → 4 a • P´ gina 2: 1 → 5 → 3 a • P´ gina 3: 6 → 5 a ´ Optima: 7 fallos de p´ gina a • P´ gina 0: 4 → 1 a • P´ gina 1: 2 → 5 a • P´ gina 2: 1 → 3 a • P´ gina 3: 6 a 80. FIFO: 7 fallos de p´ gina a • P´ gina 0: 1 → 5 → 1 a 103 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 104 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 106. • P´ gina 1: 2 → 6 a • P´ gina 2: 3 → 2 a LRU: 8 fallos de p´ gina a • P´ gina 0: 1 → 3 a • P´ gina 1: 2 → 6 → 1 a • P´ gina 2: 3 → 5 → 2 a ´ Optima: 6 fallos de p´ gina a • P´ gina 0: 1 → 5 → 6 → 1 a • P´ gina 1: 2 a • P´ gina 2: 3 a 81. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include sys/types.h #include sys/wait.h #include string.h #include time.h int tubo1[2], tubo2[2], tubo3[2], tubo4[2]; @ibaumo void cierraTuberias (void) { close (tubo1[0]); close (tubo1[1]); close (tubo2[0]); close (tubo2[1]); close (tubo3[0]); close (tubo3[1]); close (tubo4[0]); close (tubo4[1]); } void recorre (char ∗nombredir) { DIR ∗dir; struct dirent ∗entrada; struct stat datos; char ∗ruta; dir= opendir(nombredir); if (dir==NULL) { printf(Error al abrir el directorio %sn, nombredir); return; } entrada= readdir(dir); while (entrada!=NULL) { if (strcmp(entrada-d name,.) strcmp(entrada-d name,..)) { ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2); sprintf (ruta, %s/ %s,nombredir,entrada-d name); lstat (ruta,datos); if (S ISDIR(datos.st mode)) { recorre (ruta); /∗ llamada recursiva ∗/ if (rmdir(ruta)== 0) { /∗ directorio borrado ∗/ write (tubo1[1], entrada-d name, strlen(entrada-d name)); write (tubo1[1], n, 1); } 104 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 105 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 107. } else if (S ISREG (datos.st mode) (datos.st uid== getuid())) { if (time(NULL)- datos.st atime 2∗7∗24∗60∗60) { if (unlink (ruta)== 0) { /∗ fichero borrado ∗/ write (tubo1[1], entrada-d name, strlen(entrada-d name)); write (tubo1[1], n, 1); } } else /∗ el aviso ∗/ if (time(NULL)- datos.st atime 1∗7∗24∗60∗60) { write (tubo2[1], entrada-d name, strlen(entrada-d name)); write (tubo2[1], n, 1); } } free (ruta); } entrada= readdir(dir); } closedir (dir); } int main(int argc, char ∗argv[]) { int numproc; if (argc!= 2) { printf(Debes especificar una direccion de correo electronico.n); exit(1); } @ibaumo pipe (tubo1); pipe (tubo2); pipe (tubo3); pipe (tubo4); for (numproc= 0; numproc 4; numproc++) if (fork()== 0) break; switch (numproc) { case 0: dup2 (tubo1[0], STDIN FILENO); dup2 (tubo3[1], STDOUT FILENO); cierraTuberias (); execlp (sort, sort, NULL); break; case 1: dup2(tubo2 [0], STDIN FILENO); dup2(tubo4 [1], STDOUT FILENO); cierraTuberias (); execlp (sort, sort, NULL); break; case 2: dup2 (tubo3[0], STDIN FILENO); cierraTuberias (); execlp (mail, mail, argv[1], -s, Ficheros y directorios borrados, NULL); break; case 3: dup2 (tubo4[0], STDIN FILENO); cierraTuberias (); execlp (mail, mail, argv[1], -s, 105 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 106 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 108. Ficheros que se borraran en breve, NULL); break; case 4: recorre (/tmp); cierraTuberias (); wait (NULL); wait (NULL); wait (NULL); wait (NULL); } return 0; } 82. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include string.h #include sys/types.h #include sys/wait.h #define MAXLON 2000 int tubo[2]; void recorre(char ∗nombredir) { @ibaumo DIR ∗dir; struct dirent ∗entrada; struct stat datos; char ∗ruta; int pos; dir= opendir(nombredir); if (dir== NULL) { printf (Error al abrir el directorio %sn, nombredir); return; } entrada= readdir(dir); while (entrada!= NULL) { if (strcmp (entrada-d name,.) strcmp (entrada-d name,..)) { ruta= (char∗) malloc (strlen (nombredir)+ strlen (entrada-d name)+ 2); sprintf (ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta, datos); if (S ISDIR (datos.st mode)) recorre (ruta); else if (S ISREG (datos.st mode)) { pos= strlen(entrada-d name)-2; if (strcmp (entrada-d name[pos],.c)== 0 || strcmp (entrada-d name[pos],.h)== 0) { write (tubo[1], ruta, strlen(ruta)); write (tubo[1], n, 1); } } free (ruta); 106 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 107 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 109. } entrada= readdir (dir); } closedir (dir); } int main(int argc, char ∗argv[]) { char linea[MAXLON], ∗nombre; struct stat datos1, datos2; int pos; if (argc!= 3) { printf (Debe especificar dos directoriosn); exit (1); } pipe (tubo); if (fork()== 0) { close (tubo[0]); recorre (argv[1]); close (tubo[1]); } else { dup2 (tubo[0], STDIN FILENO); close (tubo[0]); close (tubo[1]); while (gets(linea)!= NULL) { pos= strlen(linea)-1; while (linea[pos]!= ’/’) @ibaumo pos--; nombre= (char∗) malloc (strlen (argv[2])+ strlen(linea[pos+1])+ 2); sprintf (nombre, %s/ %s, argv[2], linea[pos+1]); lstat (linea, datos2); if ((lstat (nombre, datos1)!= 0) || (datos1.st mtime datos2.st mtime)) { if (fork()== 0) execlp (cp, cp, linea, nombre, NULL); else wait (NULL); } free (nombre); } wait (NULL); } return 0; } 83. #include stdio.h #include stdlib.h #include sys/stat.h #include sys/wait.h #include dirent.h #include unistd.h #include time.h #include string.h int n fich= 0; int ahorro= 0; 107 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 108 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 110. void recorre (char ∗nombredir) { DIR ∗d; struct dirent ∗entrada; struct stat datosPs, datosPdf; char ∗ruta, ∗rutapdf; d= opendir(nombredir); if (d== NULL) { printf(Error al abrir el directorion); return; } entrada= readdir(d); while (entrada!=NULL) { if (strcmp(entrada-d name,.) strcmp(entrada-d name,..)) { ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2); sprintf(ruta, %s/ %s,nombredir,entrada-d name); lstat (ruta,datosPs); if (S ISDIR(datosPs.st mode)) recorre(ruta); else if (S ISREG(datosPs.st mode)) { if (strcmp(ruta[strlen(ruta)-3], .ps)== 0) {/ ∗ .ps? ∗/ rutapdf= malloc(strlen(ruta)+1); sprintf(rutapdf, %s,ruta); rutapdf[strlen(ruta)-3]=’0’; strcat (rutapdf, .pdf); if (fork()== 0) @ibaumo execlp (ps2pdf, ps2pdf, ruta, rutapdf, NULL); wait(NULL); n fich++; lstat(rutapdf,datosPdf); ahorro+= (datosPs.st blocks - datosPdf.st blocks); unlink(ruta); free(rutapdf); } } free(ruta); } entrada= readdir(d); } closedir(d); } int main(int argc, char ∗argv[]) { int i; time t inicio; if (argc== 1) { printf(Debe especificar al menos un directorion); exit(1); } for (i= 1; i argc; i++) { if (fork()== 0) { inicio= time(NULL); recorre (argv[i]); printf (Numero de ficheros transformados: %dn, n fich); printf (Ahorro de espacio en bloques: %dn, ahorro); 108 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 109 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 111. printf (Tiempo en procesar el directorio %s: %ldn, argv[i], (time(NULL)- inicio)); exit(0); } } for (i= 1; i argc; i++) wait(NULL); return 0; } 84. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include time.h #define MAX 20 struct param { int num estudiante; int num grupo; }; struct param buffer[MAX]; sem t huecos,elementos,mutex; @ibaumo int pos productor= 0; int num estudiantes, cantidad grupos, plazas por grupo; int ∗grupo de alumno; int ∗plazas libres; void init datos() { int i; grupo de alumno= (int∗)malloc(sizeof(int)∗num estudiantes); for (i= 0; i num estudiantes; i++) grupo de alumno[i]= -1; plazas libres= (int∗)malloc(sizeof(int)∗cantidad grupos); for (i= 0; i cantidad grupos; i++) plazas libres[i]= plazas por grupo; } int ∗decide preferencias (void) { int ∗peticiones; int i,pos1,pos2,aux; peticiones= (int ∗) malloc(sizeof(int)∗cantidad grupos); for (i= 0; i cantidad grupos; i++) peticiones[i]= i; for (i= 0; i cantidad grupos; i++) { pos1= random() %cantidad grupos; pos2= random() %cantidad grupos; aux= peticiones[pos1]; peticiones[pos1]= peticiones[pos2]; peticiones[pos2]= aux; 109 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 110 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 112. } return peticiones; } int grupo asignado (int num estudiante) { return (grupo de alumno[num estudiante]); } int hay plazas libres (int num grupo) { return (plazas libres[num grupo]0); } void asignar grupo (int estudiante, int grupo) { if (grupo de alumno[estudiante]==-1) { grupo de alumno[estudiante]= grupo; plazas libres[grupo]--; } else { printf(Error inesperadon); pthread exit(NULL); } } void ∗productor(void ∗p) { int num estudiante= ∗(int ∗)p; int i; int ∗peticiones; struct param dato; @ibaumo peticiones= decide preferencias (); for (i= 0; i cantidad grupos; i++) { dato.num estudiante= num estudiante; dato.num grupo= peticiones[i]; printf (El estudiante %d pide el grupo %dn, num estudiante, peticiones[i]); sem wait(huecos); sem wait(mutex); buffer[pos productor]= dato; pos productor= (pos productor+1) %MAX; sem post(mutex); sem post(elementos); if (grupo asignado(num estudiante)!=-1) pthread exit(NULL); } pthread exit(NULL); } void ∗consumidor (void ∗p) { int pos consumidor= 0; int asignados= 0; struct param dato; while (asignados num estudiantes) { sem wait(elementos); dato= buffer[pos consumidor]; pos consumidor= (pos consumidor+1) %MAX; sem post(huecos); if (hay plazas libres(dato.num grupo)) { 110 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 111 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 113. if (grupo asignado(dato.num estudiante)!=-1) printf(--¿ Peticion rechazada. Estudiante %d, grupo %d. El estudiante ya tiene grupo asignadon, dato.num estudiante,dato.num grupo); else { asignar grupo(dato.num estudiante, dato.num grupo); printf(---¿ Al estudiante %d se le asigna el grupo %dn,dato.num estudiante, dato.num grupo); asignados++; } } else printf(--¿ Peticion rechazada. Estudiante %d, grupo %d. Grupo llenon, dato.num estudiante,dato.num grupo); } pthread exit(NULL); } int main (int argc, char ∗argv[]) { pthread t ∗estudiantes, gestor; int i, ∗datos; if (argc!= 4) { printf(Error. Debe proporcionar tres parametros: Num. estudiantes, Num. de grupos y Tama˜ o de grupon); n exit(1); } @ibaumo num estudiantes= atoi(argv[1]); cantidad grupos= atoi(argv[2]); plazas por grupo= atoi(argv[3]); if (num estudiantes cantidad grupos∗plazas por grupo) { printf(Error. No hay plazas para todos los estudiantesn); exit(1); } init datos(); datos= (int∗) malloc(sizeof(int)∗num estudiantes); estudiantes= (pthread t∗) malloc(sizeof(pthread t)∗num estudiantes); sem init(huecos, 0, MAX); sem init(elementos, 0, 0); sem init(mutex, 0, 1); pthread create (gestor, NULL, consumidor, NULL); for (i= 0; i num estudiantes; i++) { datos[i]= i; pthread create (estudiantes[i], NULL, productor, datos[i]); } pthread join(gestor, NULL); return 0; } 85. #include stdio.h #include stdlib.h 111 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 112 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 114. #include sys/stat.h #include dirent.h #include unistd.h #include string.h #include time.h #include sys/types.h #include sys/wait.h void recorre(char ∗nombredir) { DIR ∗d; struct dirent ∗entrada; struct stat datos; char ∗ruta; d= opendir(nombredir); if(d==NULL){ printf(Error al abrir el directorio %sn,nombredir); return; } entrada= readdir(d); while (entrada!= NULL) { if(strcmp(entrada-d name,.) strcmp(entrada-d name,..)) { ruta=malloc(strlen(nombredir)+strlen(entrada-d name)+2); sprintf(ruta, %s/ %s,nombredir,entrada-d name); lstat(ruta,datos); if (S ISDIR(datos.st mode)) recorre(ruta); @ibaumo else if(fork()== 0) if (datos.st size2∗1024∗1024) execlp(lpr,lpr,-P,ps1,ruta,NULL); else execlp(lpr,lpr,-P,ps2,ruta,NULL); else wait(NULL); free(ruta); } entrada= readdir(d); } closedir(d); } int main(int argc,char ∗argv[]) { int num; time t inicio,fin; inicio= time(NULL); for (num= 1; num argc; num++) if (fork()== 0) { recorre(argv[num]); exit(0); } for (num= 1; num argc; num++) wait(NULL); fin=time(NULL); 112 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 113 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 115. printf(Duracion: %ld segundosn,fin-inicio); return 0; } 86. #include stdlib.h #include stdio.h #include semaphore.h #include pthread.h #include unistd.h #include time.h #define N 30 typedef struct { int id; int tiempo; } param; sem t svar, slect, stam; int ngallo= 0; void comer(){} void beber(){} void dormir (int id, int tiempo){ sleep(tiempo); printf(El gallo %d ha dormido %d horasn,id,tiempo); } @ibaumo void ∗galloSalvaje (void ∗datos) { param ∗mi dato= (param ∗)datos; int iden= mi dato-id; int temp= mi dato-tiempo; while(1){ comer(); sem wait(svar); printf(El gallo salvaje %d esta bebiendon,iden); beber(); printf(El gallo salvaje %d ha terminado de bebern,iden); sem post(svar); dormir(iden,temp); } pthread exit(NULL); } void ∗galloDomestico (void ∗ datos) { param ∗mi dato= (param ∗)datos; int iden= mi dato-id; int temp= mi dato-tiempo; while(1){ comer(); sem wait(slect); ngallo++; 113 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 114 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 116. if(ngallo==1) sem wait(svar); sem post(slect); sem wait(stam); printf(El gallo domestico %d esta bebiendon,iden); beber(); printf(El gallo domestico %d ha terminado de bebern,iden); sem post(stam); sem wait(slect); ngallo--; if(ngallo==0) sem post(svar); sem post(slect); dormir(iden,temp); } pthread exit(NULL); } int main (int argc,char ∗argv[]){ pthread t th[N]; int i; param vector[N]; sem init(svar,0,1); sem init(slect,0,1); sem init(stam,0,6); for(i=0;i25;i++){ /∗ crea los gallos domesticos ∗/ @ibaumo vector[i].tiempo=7+random() %4; vector[i].id=i; pthread create(th[i],NULL,galloDomestico,(void ∗) vector[i]); } for(i=25;iN;i++){ /∗ crea los gallos salvajes ∗/ vector[i].tiempo=7+random() %4; vector[i].id=i; pthread create(th[i],NULL,galloSalvaje,(void ∗) vector[i]); } for(i=0;iN;i++) pthread join(th[i],NULL); sem destroy(svar); sem destroy(slect); sem destroy(stam); exit(0); } 87. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include math.h #include stdbool.h #define MAX 5 int buffer[MAX]; 114 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 115 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 117. sem t huecos, elementos, pos prod, prod; int pos productor=0, cont prod= 0, cont primos= 0; int suma digitos es impar (int numero) { int suma= 0; while (numero0) { suma+= numero %10; numero/= 10; } return (suma %2==1); } int es primo(int numero) { int divisor; for (divisor=2; divisor= sqrt(numero); divisor++) if (numero %divisor==0) return 0; return 1; } void ∗productor(void ∗p) { int i, dato; for (i= 0;i 1000; i++) { dato= random() %1000; sem wait(prod); cont prod++; @ibaumo sem post(prod); if (es primo(dato)) { sem wait(huecos); sem wait(pos prod); buffer[pos productor]= dato; pos productor= (pos productor+1) %MAX; sem post(pos prod); sem post(elementos); } } sem wait(huecos); sem wait(pos prod); buffer[pos productor]= -1; pos productor= (pos productor+1) %MAX; sem post(pos prod); sem post(elementos); pthread exit(NULL); } void ∗consumidor(void ∗p) { int pos consumidor=0; int dato, cont= 0, term= 0; bool fin= false; while (!fin) { sem wait(elementos); dato= buffer[pos consumidor]; pos consumidor= (pos consumidor+1) %MAX; sem post(huecos); 115 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 116 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 118. if (dato== -1) { term++; if (term== 3) fin= true; } else { cont primos++; if (suma digitos es impar(dato)) { printf( %d ,dato); fflush(stdout); cont++; if (cont== 50) fin= true; } } } pthread exit(NULL); } int main(int argc, char ∗argv[]) { pthread t th[4]; int i; sem init(huecos, 0, MAX); sem init(elementos, 0, 0); sem init(pos prod, 0, 1); sem init(prod, 0, 1); for (i= 0; i 3; i++) @ibaumo pthread create (th[i], NULL, productor, NULL); pthread create (th[3], NULL, consumidor, NULL); pthread join(th[3], NULL); printf (n); printf (Numeros primos procesados: %dn, cont primos); printf (Numeros alatorios generados: %dn, cont prod); sem destroy(huecos); sem destroy(elementos); sem destroy(pos prod); sem destroy(prod); return 0; } 88. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include sys/types.h #include sys/wait.h #include string.h #include time.h int tubo1[2], tubo2[2]; void cierraTuberias (void) { close (tubo1[0]); close (tubo1[1]); 116 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 117 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 119. close (tubo2[0]); close (tubo2[1]); } void recorre (char ∗nombredir) { DIR ∗d; struct dirent ∗entrada; struct stat datos; char ∗ruta; d= opendir(nombredir); if (d==NULL) { printf(Error al abrir el directorio %sn, nombredir); return; } entrada= readdir(d); while (entrada!=NULL) { if (strcmp(entrada-d name,.) strcmp(entrada-d name,..)) { ruta= malloc(strlen(nombredir)+strlen(entrada-d name)+2); sprintf (ruta, %s/ %s,nombredir,entrada-d name); lstat (ruta,datos); if (S ISDIR(datos.st mode)) { recorre (ruta); if (rmdir(ruta)== 0) { write(tubo1[1], entrada-d name, strlen(entrada-d name)); write(tubo1[1], n, 1); } @ibaumo } else if (S ISREG (datos.st mode) (datos.st uid == getuid())) { if (datos.st size 2∗1024∗1024) { if (unlink(ruta)== 0) { write(tubo1[1], entrada-d name, strlen(entrada-d name)); write(tubo1[1], n, 1); } } else if (datos.st size 1∗1024∗1024) { write(tubo2[1], entrada-d name, strlen(entrada-d name)); write(tubo2[1], n, 1); } } free(ruta); } entrada= readdir(d); } closedir(d); } int main(int argc, char ∗argv[]) { int i; if (argc!=2) { printf(Debe especificar una direccion de correo electronicon); exit(1); } 117 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 118 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 120. pipe (tubo1); pipe (tubo2); for (i= 0; i 2; i++) if (fork()== 0) break; switch (i) { case 0: dup2(tubo1[0], STDIN FILENO); cierraTuberias(); execlp (mail, mail, argv[1], -s, Ficheros y directorios borrados de tmp, NULL); break; case 1: dup2(tubo2[0], STDIN FILENO); cierraTuberias(); execlp (mail, mail, argv[1], -s, Ficheros que ocupan mucho espacio en tmp, NULL); break; case 2: recorre(/tmp); cierraTuberias(); wait (NULL); wait (NULL); break; } return 0; } @ibaumo 89. Soluci´ n al apartado a): o #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #define N vehiculos 200 sem t estacion; void ∗camion (void ∗ nada) { long int n= (long int) pthread self(); printf (Llega camion: %ldn, n); sem wait(estacion); sem post(estacion); printf (Se atiende camion: %ldn, n); sleep(random() %3+2); /∗ tiempo invertido en atender al camion ∗/ printf (Sale camion: %ldn, n); pthread exit(NULL); } void ∗barco (void ∗ nada) { long int n= (long int) pthread self(); printf (Llega barco: %ldn, n); sem wait(estacion); printf(Se atiende barco: %ldn, n); sleep(random() %5+5); /∗ tiempo invertido en atender al barco ∗/ 118 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 119 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 121. printf (Sale barco: %ldn, n); sem post(estacion); pthread exit(NULL); } int main(int argc, char ∗argv[]) { int i; pthread t th[N vehiculos]; sem init(estacion, 0, 1); for (i= 0; i N vehiculos; i++) { sleep(random() %3); if (random() %100 95) pthread create(th[i], NULL, camion, NULL); else pthread create(th[i], NULL, barco, NULL); } for (i= 0; i N vehiculos; i++) pthread join(th[i], NULL); sem destroy(estacion); return 0; } Soluci´ n al apartado b): o #include stdio.h #include stdlib.h @ibaumo #include semaphore.h #include pthread.h #include unistd.h #define N vehiculos 200 sem t estacion, camiones; int ncamiones= 0; void ∗camion (void ∗ nada) { long int n= (long int) pthread self(); printf (Llega camion: %ldn, n); sem wait(camiones); ncamiones++; if (ncamiones== 1) sem wait(estacion); sem post(camiones); printf (Se atiende camion: %ldn, n); sleep(random() %3+2); /∗ tiempo invertido en atender al camion ∗/ printf (Sale camion: %ldn, n); sem wait(camiones); ncamiones--; if (ncamiones== 0) sem post(estacion); sem post(camiones); pthread exit(NULL); } 119 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 120 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 122. void ∗barco (void ∗ nada) { long int n= (long int) pthread self(); printf (Llega barco: %ldn, n); sem wait(estacion); printf(Se atiende barco: %ldn, n); sleep(random() %5+5); /∗ tiempo invertido en atender al barco ∗/ printf (Sale barco: %ldn, n); sem post(estacion); pthread exit(NULL); } int main(int argc, char ∗argv[]) { int i; pthread t th[N vehiculos]; sem init(estacion, 0, 1); sem init(camiones, 0, 1); for (i= 0; i N vehiculos; i++) { sleep(random() %3); if (random() %100 95) pthread create(th[i], NULL, camion, NULL); else pthread create(th[i], NULL, barco, NULL); } for (i= 0; i N vehiculos; i++) pthread join(th[i], NULL); @ibaumo sem destroy(estacion); sem destroy(camiones); return 0; } 90. #include stdio.h #include sys/types.h #include wait.h #include unistd.h #include stdlib.h #include sys/stat.h #include fcntl.h #include time.h int main (int argc, char ∗argv[]) { int tub1[2],tub2[2]; int fich; time t ini, fin; if (fork()!= 0) { ini=time(NULL); wait(NULL); fin= time(NULL); printf (Tiempo total: %ld segundosn, fin-ini); return 0; } pipe (tub1); if (fork()!= 0){ dup2 (tub1[0], STDIN FILENO); 120 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 121 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 123. close (tub1[0]); close (tub1[1]); fich= creat (argv[3], 00644); dup2 (fich, STDOUT FILENO); close(fich); execlp (uniq, uniq, NULL); } else { pipe (tub2); if (fork()!= 0){ dup2 (tub1[1],STDOUT FILENO); dup2 (tub2[0],STDIN FILENO); close (tub1[1]); close (tub1[0]); close (tub2[1]); close (tub2[0]); execlp (sort, sort, -r, NULL); } else { dup2 (tub2[1], STDOUT FILENO); close (tub1[0]); close (tub1[1]); close (tub2[0]); close (tub2[1]); execlp (grep, grep, argv[1], argv[2], NULL); } } } 91. Soluci´ n al apartado a): o #include stdlib.h @ibaumo #include stdio.h #include semaphore.h #include pthread.h #include unistd.h #include time.h #define N hilos 200 sem t sbanco, scliente; int ncliente= 0; void ∗cliente(void ∗n){ int id= ∗(int ∗) n; sleep(random() %100); printf (Llega el cliente %dn,id); sem wait (scliente); ncliente++; if (ncliente== 1) sem wait (sbanco); sem post (scliente); sleep(random() %3+2); /∗/ tiempo de espera en la cola ∗/ printf (Se atiende al cliente: %dn, id); sleep(random() %3+2); /∗ tiempo invertido en atenderle ∗/ sem wait (scliente); ncliente--; printf (Sale el cliente %dn, id); if (ncliente== 0) sem post (sbanco); 121 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 122 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 124. sem post (scliente); pthread exit(NULL); } void ∗furgon (void ∗n) { int id= ∗(int ∗) n; sleep (random() %100); printf (Llega el furgon %dn,id); sem wait (sbanco); printf (Se atiende a los guardias %dn, id); sleep (random() %5 + 5); /∗ tiempo invertido en atenderlos ∗/ printf (Se va el furgon %dn, id); sem post (sbanco); pthread exit(NULL); } int main (int argc, char ∗argv[]) { pthread t hilo[N hilos]; int id[N hilos]; int i, furgon creado= 0; sem init(sbanco, 0, 1); sem init(scliente, 0, 1); @ibaumo for (i= 0; i N hilos; i++){ id[i]= i; if(furgon creado== 1) pthread create (hilo[i], NULL, cliente, (void ∗)id[i]); else if (random() %100 95) pthread create (hilo[i], NULL, cliente, (void ∗)id[i]); else { pthread create (hilo[i], NULL, furgon, (void ∗)id[i]); furgon creado= 1; } } for (i= 0; i N hilos; i++) pthread join (hilo[i],NULL); sem destroy(sbanco); sem destroy(scliente); return 0; } Soluci´ n al apartado b): o #include stdlib.h #include stdio.h #include semaphore.h #include pthread.h #include unistd.h #include time.h #define N hilos 200 122 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 123 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 125. sem t sbanco, scliente, sorden; int ncliente= 0; void ∗cliente(void ∗n){ int id= ∗(int ∗) n; sleep(random() %100); printf (Llega el cliente %dn,id); sem wait (sorden); sem post (sorden); sem wait (scliente); ncliente++; if (ncliente== 1) sem wait (sbanco); sem post (scliente); sleep(random() %3+2); /∗/ tiempo de espera en la cola ∗/ printf (Se atiende al cliente: %dn, id); sleep(random() %3+2); /∗ tiempo invertido en atenderle ∗/ sem wait (scliente); ncliente--; printf (Sale el cliente %dn, id); if (ncliente== 0) sem post (sbanco); sem post (scliente); pthread exit(NULL); @ibaumo } void ∗furgon (void ∗n) { int id= ∗(int ∗) n; sleep (random() %100); printf (Llega el furgon %dn,id); sem wait (sorden); sem wait (sbanco); printf (Se atiende a los guardias %dn, id); sleep (random() %5 + 5); /∗ tiempo invertido en atenderlos ∗/ printf (Se va el furgon %dn, id); sem post (sbanco); sem post (sorden); pthread exit(NULL); } int main (int argc, char ∗argv[]) { pthread t hilo[N hilos]; int id[N hilos]; int i, furgon creado= 0; sem init(sbanco, 0, 1); sem init(scliente, 0, 1); sem init(sorden, 0, 1); 123 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 124 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 126. for (i= 0; i N hilos; i++){ id[i]= i; if(furgon creado== 1) pthread create (hilo[i], NULL, cliente, (void ∗)id[i]); else if (random() %100 95) pthread create (hilo[i], NULL, cliente, (void ∗)id[i]); else { pthread create (hilo[i], NULL, furgon, (void ∗)id[i]); furgon creado= 1; } } for (i= 0; i N hilos; i++) pthread join (hilo[i],NULL); sem destroy(sbanco); sem destroy(scliente); sem destroy(sorden); return 0; } 92. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include time.h @ibaumo #define MAX 10 #define N PROD 3 #define N CONS 2 int buffer[MAX]; sem t huecos, elementos, sprod, scon, sfin; int pos productor= 0, pos consumidor= 0; int cont= 0; int generar dato(void) {return random() %256;} int numero aleatorio(void){return random() %100;} void ∗productor (void ∗nada) { int i, dato, n= numero aleatorio(); for (i= 0; i n; i++){ dato= generar dato(); sleep(random() %2); sem wait (huecos); sem wait (sprod); buffer[pos productor]= dato; pos productor= (pos productor+ 1) %MAX; sem post (sprod); sem post (elementos); } sem wait (sfin); cont++; 124 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 125 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 127. if (cont== N PROD) /∗ si soy el ultimo productor ∗/ for (i= 0; i N CONS ; i++){ /∗ por cada consumidor ∗/ sem wait(huecos); buffer[pos productor]= -1; pos productor= (pos productor+ 1) %MAX; sem post(elementos); } sem post (sfin); pthread exit(NULL); } void ∗consumidor(void ∗nada){ int dato= 0; while (dato!= -1) { sem wait(elementos); sem wait(scon); dato= buffer[pos consumidor]; pos consumidor= (pos consumidor+ 1) %MAX; sem post(scon); sem post(huecos); if (dato!= -1) { printf( %d ,dato); fflush(stdout); } sleep(random() %2); } @ibaumo pthread exit(NULL); } int main(int argc,char ∗argv[]){ pthread t th[N PROD+N CONS]; int i=0; sem init (huecos,0,MAX); sem init (elementos,0,0); sem init (sprod,0,1); sem init (scon,0,1); sem init (sfin,0,1); for (i=0; i N PROD; i++) pthread create (th[i], NULL, productor, NULL); for (i=0; i N CONS; i++) pthread create (th[i+N PROD], NULL, consumidor, NULL); for (i=0; i N PROD + N CONS; i++) pthread join (th[i], NULL); sem destroy (huecos); sem destroy (elementos); sem destroy (sprod); sem destroy (scon); sem destroy (sfin); return 0; } 125 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 126 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 128. 93. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include string.h #include pthread.h #include semaphore.h int cont enlaces= 0; sem t critico; void recorre(char ∗nombredir) { DIR ∗d; struct dirent ∗entrada; struct stat datos; char ∗ruta; d= opendir(nombredir); if (d== NULL) { printf(Error al abrir el directorion); return; } entrada= readdir(d); while (entrada!= NULL) { if (strcmp(entrada-d name,.) strcmp(entrada-d name,..)) { ruta= (char ∗)malloc (strlen(nombredir)+ @ibaumo strlen(entrada-d name)+2); sprintf(ruta, %s/ %s,nombredir,entrada-d name); lstat(ruta,datos); if (S ISDIR(datos.st mode)) { /∗ es un directorio? ∗/ if (datos.st uid== getuid()) /∗ pertenece al usuario? ∗/ recorre(ruta); else printf ( %s no pertenece al usuarion, ruta); } else if (S ISLNK(datos.st mode)) { /∗ es un enlace blando? ∗/ sem wait(critico); cont enlaces++; sem post(critico); } free(ruta); } entrada= readdir(d); } closedir(d); } void ∗ busca (void ∗dato) { struct stat datos; char ∗nombredir= (char ∗)dato; lstat (nombredir, datos); if (S ISDIR(datos.st mode)) if (datos.st uid== getuid()) recorre(nombredir); else printf ( %s no pertenece al usuarion, nombredir); 126 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 127 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 129. else printf ( %s no es un directorion, nombredir); pthread exit(NULL); } int main(int argc, char ∗argv[]) { pthread t hilo[argc-1]; int i; if (argc== 1) { printf(Debe especificar al menos un directorion); exit(1); } sem init (critico, 0, 1); for (i= 0; i argc-1; i++) pthread create (hilo[i], NULL, busca, (void ∗) argv[i+1]); for (i= 0; i argc-1; i++) pthread join (hilo[i], NULL); printf (Enlaces encontrados: %dn, cont enlaces); sem destroy (critico); return 0; } 94. #include stdio.h #include stdlib.h @ibaumo #include sys/stat.h #include unistd.h #include sys/types.h #include sys/wait.h #include stdbool.h #include math.h int es primo(int numero) { int divisor; for (divisor=2; divisor= sqrt(numero); divisor++) if (numero %divisor==0) return 0; return 1; } void productor (int inicio, int fin, int tubo[2], int tubo fin[2]) { int numero; int contador primos= 0; close (tubo[0]); close (tubo fin[0]); for (numero= inicio; numero= fin; numero++) if (es primo(numero)) { write (tubo[1], numero, sizeof(int)); contador primos++; } close (tubo[1]); write (tubo fin[1], contador primos, sizeof(int)); 127 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 128 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 130. close (tubo fin[1]); } void consumidor (int tubo[2], int tubo fin[2]) { int datos[2]; int leidos; int contador claves= 0; bool fin= false; close (tubo[1]); close (tubo fin[1]); while (!fin) { leidos= read(tubo[0], datos, 2∗sizeof(int)); if (leidos== 0) /∗ ya no hay mas datos en la tuberia ∗/ fin= true; else if (es primo((datos[0]-1)/2) es primo((datos[1]-1)/2)) { printf (Los numeros %d y %d forman la clave %dn, datos[0], datos[1], datos[0]∗datos[1]); contador claves++; } } close (tubo[0]); read (tubo fin[0], datos, 2∗sizeof(int)); close (tubo fin[0]); @ibaumo printf (Resumen finaln); printf (Se han encontrado %d numeros primos y %d claves criptograficasn, datos[0]+datos[1], contador claves); } int main (int argc, char∗argv[]) { int desde, mitad, hasta; int tubo[2], tubo fin[2]; if (argc!=3) { printf (Error, debe especificar el rango de numeros a analizarn); exit(1); } desde= atoi(argv[1]); /∗ se asume que son numeros validos ∗/ hasta= atoi(argv[2]); mitad=(desde+hasta)/2; pipe(tubo); pipe(tubo fin); if (fork()!= 0) if (fork()!= 0) { consumidor(tubo, tubo fin); wait(NULL); wait(NULL); } else productor (desde, mitad, tubo, tubo fin); else productor(mitad+1, hasta, tubo, tubo fin); 128 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 129 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 131. return 0; } 95. #include stdio.h #include unistd.h #include stdlib.h #include semaphore.h #include pthread.h #include math.h #include stdbool.h #define MAX 20 #define N PROD 2 #define FIN -1 int contador primos= 0; sem t critico, elementos, huecos, primos; int buffer[MAX]; int pos productor= 0; int es primo(int numero) { int divisor; for (divisor=2; divisor= sqrt(numero); divisor++) if (numero %divisor==0) return 0; return 1; } @ibaumo void ∗ productor (void ∗ dato){ int ∗data = (int ∗)dato; int numero; int inicio = data[0]; int fin = data[1]; for (numero= inicio; numero= fin; numero++) if (es primo(numero)){ sem wait(huecos); sem wait(critico); buffer[pos productor]= numero; pos productor=(pos productor+1) %MAX; sem post(critico); sem post(elementos); sem wait(primos); contador primos++; sem post(primos); } sem wait(huecos); sem wait(critico); buffer[pos productor]= FIN; pos productor=(pos productor+1) %MAX; sem post(critico); sem post(elementos); pthread exit(NULL); } 129 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 130 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 132. void ∗consumidor (void ∗ nada){ int datos[2]; int dato,pos consumidor= 0; int par= 0; bool fin= false; int contador claves= 0, cont= 0; while (!fin) { sem wait(elementos); dato=buffer[pos consumidor]; pos consumidor=(pos consumidor+1) %MAX; sem post(huecos); if (dato== FIN) { cont++; if (cont== N PROD) fin= true; } else { if (par %2== 0) datos[0]= dato; else { datos[1]= dato; if (es primo((datos[0]-1)/2) es primo((datos[1]-1)/2)) { printf(Los numeros %d y %d forma la clave %dn, datos[0], datos[1], datos[0]∗datos[1]); contador claves++; } } par++; } @ibaumo } printf(Resumen finaln); printf(Se han encontrado %d numeros primos y %d claves criptograficasn, contador primos, contador claves); pthread exit(NULL); } int main (int argc,char ∗argv[]) { int desde, mitad, hasta; pthread t th1,th2,th3; int data1[2], data2[2]; if (argc!= 3){ printf (Error, debe especificar el rango de numeros a analizarn); exit(1); } desde= atoi(argv[1]); /∗ se asume que los numeros son validos ∗/ hasta= atoi(argv[2]); mitad= (desde+hasta)/2; sem init (critico, 0, 1); sem init (primos, 0, 1); sem init (elementos, 0, 0); sem init (huecos, 0, MAX); data1[0]= desde; data1[1]= mitad; data2[0]= mitad+1; 130 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 131 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 133. data2[1]= hasta; pthread create (th1, NULL, productor, (void ∗)data1); pthread create (th2, NULL, productor, (void ∗)data2); pthread create (th3, NULL, consumidor, NULL); pthread join (th1,NULL); pthread join (th2,NULL); pthread join (th3,NULL); sem destroy (critico); sem destroy (primos); sem destroy (elementos); sem destroy (huecos); return 0; } 96. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include string.h #include sys/types.h #include sys/wait.h #include unistd.h #include time.h #include fcntl.h @ibaumo time t inicio; int tubo[2]; void recorre (char ∗nombredir) { DIR ∗d; struct dirent ∗entrada; struct stat datos; char ∗ruta; d= opendir (nombredir); if (d== NULL) { printf(Error al abrir el directorio %sn, nombredir); return; } entrada= readdir(d); while (entrada!= NULL) { if (strcmp (entrada-d name,.) strcmp (entrada-d name,..)) { ruta= malloc (strlen (nombredir)+ strlen (entrada-d name)+2); sprintf (ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta,datos); if (S ISDIR (datos.st mode)) recorre(ruta); else if (S ISREG (datos.st mode)) { if ((inicio- datos.st mtime 60∗60) (datos.st uid== getuid())) { write (tubo[1], ruta, strlen(ruta)); write (tubo[1], n, 1); 131 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 132 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 134. if (fork()== 0) execlp (zip, zip, /tmp/comprimido.zip, ruta, NULL); else wait(NULL); } } free(ruta); } entrada=readdir(d); } closedir(d); } int main (int argc,char ∗argv[]) { int fichero; inicio= time(NULL); if (argc!= 2) { printf (Indica un directorio como parametron); exit(0); } pipe(tubo); if (fork()== 0){ close (tubo[0]); recorre (argv[1]); close (tubo[1]); } else { fichero= creat (usuario.log, 00644); @ibaumo dup2 (fichero, STDOUT FILENO); dup2 (tubo[0], STDIN FILENO); close (fichero); close (tubo[0]); close (tubo[1]); execlp (sort, sort, NULL); } exit(0); } 97. La soluci´ n que se presenta a continuaci´ n incluye los dos puntos indicados o o en el enunciado donde el sem´ foro orden se ha utilizado para resolver el a segundo punto. #include stdio.h #include stdlib.h #include semaphore.h #include pthread.h #include unistd.h #include sys/syscall.h #define N atletas 30 sem t instalaciones, corredores, orden; int cont= 0; void ∗corredor (void ∗ nada) { int n= (int) syscall(SYS gettid); 132 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 133 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 135. sem wait(orden); printf (Llega corredor: %dn, n); sem wait(corredores); cont++; if (cont== 1) sem wait(instalaciones); printf (Entra en las instalaciones el corredor %dn, n); sem post(corredores); sem post(orden); sleep(random() %3); /∗ tiempo invertido en usarlas ∗/ sem wait(corredores); cont--; printf (Sale de las instalaciones el corredor: %dn, n); if (cont== 0) sem post(instalaciones); sem post(corredores); pthread exit(NULL); } void ∗jabalino (void ∗ nada) { int n= (int) syscall(SYS gettid); sem wait(orden); printf (Llega lanzador de jabalina: %dn, n); sem wait(instalaciones); printf (Entra en las instalaciones el jabalino %dn, n); @ibaumo sleep(random() %3+2); /∗ tiempo invertido en usarlas ∗/ printf (Sale de las instalaciones el jabalino: %dn, n); sem post(instalaciones); sem post(orden); pthread exit(NULL); } void ∗martillo (void ∗ nada) { int n= (int) syscall(SYS gettid); sem wait(orden); printf (Llega lanzador de martillo: %dn, n); sem wait(instalaciones); printf (Entra en las instalaciones el martillo %dn, n); sleep(random() %3+2); /∗ tiempo invertido en usarlas ∗/ printf (Sale de las instalaciones el martillo: %dn, n); sem post(instalaciones); sem post(orden); pthread exit(NULL); } int main (int argc, char ∗argv[]) { int num; pthread t th[N atletas]; sem init (instalaciones, 0, 1); sem init (corredores, 0, 1); sem init (orden, 0, 1); 133 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 134 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 136. for (num= 0; num N atletas; num++) { sleep(random() %3); if (random() %100 66) pthread create (th[num], NULL, corredor, NULL); else if (random() %100 82) pthread create (th[num], NULL, jabalino, NULL); else pthread create (th[num], NULL, martillo, NULL); } for (num= 0; num N atletas; num++) pthread join(th[num], NULL); sem destroy (instalaciones); sem destroy (corredores); sem destroy (orden); return 0; } 98. #include stdio.h #include stdlib.h #include unistd.h #include time.h #include pthread.h #include string.h #include semaphore.h @ibaumo #define NHILOS 100 #define PAISES 10 typedef struct { int pais; int valor; } params; char paises[PAISES][30]={ Espa˜ a, Portugal, Francia, n Ucrania, Letonia, Servia, Israel, Alemania, Italia, Holanda}; int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0}; sem t srecurso[PAISES],sjurado; int njurados= 0; void ∗voto (void ∗dato) { params ∗mi dato= (params∗) dato; int pais= mi dato-pais; int puntos=mi dato-valor; sleep(random() %2); sem wait(srecurso[pais]); printf (Voto al pais %s %d puntosn, paises[pais],puntos); puntuaciones[pais]+= puntos; printf (Ya he votado al pais %s %d puntosn, paises[pais],puntos); sem post(srecurso[pais]); pthread exit(NULL); } 134 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 135 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 137. void ∗consulta (void ∗dato) { int pais= ∗(int∗)dato, num; sleep(random() %2); sem wait(sjurado); njurados++; if (njurados== 1) for (num= 0; num PAISES; num++) sem wait(srecurso[num]); printf(El pais %d realiza la consultan, pais); sem post(sjurado); for (num= 0; num PAISES; num++) printf (( %s, %d)n, paises[num], puntuaciones[num]); sem wait(sjurado); njurados--; printf (El pa´s %d termina la consultan, pais); ı if (njurados== 0) for (num= 0; num PAISES; num++) sem post (srecurso[num]); sem post(sjurado); pthread exit(NULL); } int main (int argc,char ∗argv[]) { @ibaumo pthread t hilo[NHILOS]; int num, pais, idPais[NHILOS]; params unvoto[NHILOS]; for (num= 0; num PAISES; num++) sem init (srecurso[num], 0, 1); sem init (sjurado, 0, 1); for (num= 0; num NHILOS; num++){ pais= random() %PAISES; if (random() %100 90) { unvoto[num].pais= pais; unvoto[num].valor= random() %10; pthread create (hilo[num], NULL, voto, (void ∗)unvoto[num]); } else { idPais[num]= pais; pthread create (hilo[num], NULL, consulta, (void ∗)idPais[num]); } } for (num= 0; num NHILOS; num++) pthread join(hilo[num],NULL); for (num=0; num PAISES; num++) sem destroy(srecurso[num]); sem destroy(sjurado); return 0; } 135 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 136 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 138. 99. #include stdio.h #include stdlib.h #include unistd.h #include sys/types.h #include sys/wait.h #include string.h #define N 100 #define PAISES 10 char paises[PAISES][10]={Espa˜ a, Portugal, Francia, Ucrania, n Letonia, Servia, Israel, Alemania, Italia, Holanda}; int puntuaciones[PAISES]={0,0,0,0,0,0,0,0,0,0}; int main (int argc,char ∗argv[]) { int num, dato[2]; int tubA[2],tubB[2]; char ∗linea; pipe(tubA); for (num= 0; num N; num++){ if (fork()== 0){ srandom (getpid()); dato[0]= random() %PAISES; dato[1]= random() %10; printf (Soy el votante %d, mi voto es para el pais %d %d puntosn, num, dato[0], dato[1]); close (tubA[0]); @ibaumo write (tubA[1], dato, 2∗sizeof(int)); close (tubA[1]); exit (0); } } close (tubA[1]); while (read (tubA[0], dato, 2∗sizeof(int))) puntuaciones[dato[0]]+= dato[1]; close (tubA[0]); printf(La votacion resultante es:n); printf((pais,numero de votos)n); for (num= 0; num PAISES; num++) printf (( %s, %d)n, paises[num], puntuaciones[num]); pipe(tubB); if (fork()!= 0) { close (tubB[0]); for (num= 0; num PAISES; num++){ linea= (char∗) malloc (strlen (paises[num])+ 15); sprintf (linea, %3d puntos, %sn, puntuaciones[num], paises[num]); write (tubB[1], linea, strlen(linea)); free (linea); } close (tubB[1]); } else { dup2 (tubB[0],STDIN FILENO); close (tubB[1]); close (tubB[0]); 136 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 137 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 139. execlp (sort, sort, -r, NULL); } for (num= 0; num N+1; num++) printf (Fin del proceso de PID %d.n, wait(NULL)); return 0; } 100. #include stdio.h #include stdlib.h #include sys/stat.h #include dirent.h #include unistd.h #include string.h #include sys/types.h #include sys/wait.h int cuenta= 0, tubo1[2], tubo2[2]; void recorre (char ∗nombredir) { DIR ∗d; struct dirent ∗entrada; struct stat datos; char ∗ruta; char dato[10]; d= opendir(nombredir); @ibaumo if (d== NULL) return; entrada= readdir(d); while (entrada!=NULL) { if (strcmp(entrada-d name, .) strcmp(entrada-d name, ..)) { ruta= malloc (strlen(nombredir)+ strlen(entrada-d name)+2); sprintf (ruta, %s/ %s, nombredir, entrada-d name); lstat (ruta, datos); if (S ISDIR(datos.st mode)) recorre (ruta); else if (datos.st blocks 1024) { sprintf (dato, %ldn, (long int)datos.st ino); write (tubo1[1], dato, strlen(dato)); cuenta++; } free(ruta); } entrada= readdir(d); } closedir (d); } int main (int argc, char ∗argv[]) { int num, dato, total= 0; pipe(tubo1); pipe(tubo2); 137 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 138 100 Ejercicios resueltos de Sistemas Operativos - UJI
  • 140. for (num= 1; num argc; num++) if (fork()== 0) { /∗ procesos de busqueda ∗/ close (tubo1[0]); close (tubo2[0]); recorre (argv[num]); write (tubo2[1], cuenta, sizeof(int)); close (tubo1[1]); close (tubo2[1]); exit(0); } if (fork()== 0) { /∗ proceso de ordenacion ∗/ dup2 (tubo1[0], STDIN FILENO); close (tubo1[0]); close (tubo1[1]); close (tubo2[0]); close (tubo2[1]); execlp (sort, sort, NULL); } close (tubo1[0]); /∗ proceso principal ∗/ close (tubo1[1]); close (tubo2[1]); while (read (tubo2[0], dato, sizeof(int))!= 0) total+= dato; close(tubo2[0]); for (num= 0; num argc; num++) wait(NULL); printf (Total de ficheros encontrados %dn, total); @ibaumo return 0; } 138 J. Ribelles / J. Martínez / P. García - ISBN: 978-84-693-0148-7 139 100 Ejercicios resueltos de Sistemas Operativos - UJI