SHARE
TWEET

Ricardo

a guest Aug 30th, 2010 252 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include <cstring>
  3.  
  4. #include <unistd.h>
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7.  
  8. #include <sys/shm.h>
  9. #include <sys/types.h>
  10. #include <sys/ipc.h>
  11. #include <sys/sem.h>
  12.  
  13. #include <wait.h>
  14. #include <assert.h>
  15.  
  16. /*
  17.  * Diagrama de precedencia:
  18.  *
  19.  *              inicial()
  20.  *                 |
  21.  *                 |
  22.  *                /|\
  23.  *               / | \
  24.  *              /  |  \
  25.  *             /   |   \
  26.  *            /    |    \
  27.  *           P1    P2    P3
  28.  *            \    |    /
  29.  *             \   |   /
  30.  *              \  |  /
  31.  *               \ | /
  32.  *                \|/
  33.  *                 |
  34.  *                 |
  35.  *               final()
  36.  *
  37.  */
  38.  
  39. union semun {
  40.     int val;                    /* value for SETVAL */
  41.     struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
  42.     unsigned short int *array;  /* array for GETALL, SETALL */
  43.     struct seminfo *__buf;      /* buffer for IPC_INFO */
  44. };
  45.  
  46. pid_t pid_hijo1;
  47. pid_t pid_hijo2;
  48. pid_t pid_hijo3;
  49. pid_t pid_hijo4;
  50.  
  51. key_t key_shared;
  52.  
  53. int id_heap;
  54. int *mini_heap = NULL;
  55. int sem_id;
  56.  
  57. // Estructura de 100 bytes
  58. class Mensaje
  59. {
  60. public:
  61.     Mensaje()
  62.     {
  63.         a = 0;
  64.         b = 0;
  65.         c = 0;
  66.         d = 0;
  67.         e = 0;
  68.         f = 0;
  69.         g = 0;
  70.         h = 0;
  71.         i = 0;
  72.         j = 0;
  73.         k = 0;
  74.         l = 0;
  75.         a2 = 0;
  76.         b2 = 0;
  77.         c2 = 0;
  78.         d2 = 0;
  79.         e2 = 0;
  80.         f2 = 0;
  81.         g2 = 0;
  82.         h2 = 0;
  83.         i2 = 0;
  84.         j2 = 0;
  85.         k2 = 0;
  86.         l2 = 0;
  87.         z = 0;
  88.     }
  89.  
  90.     int a;
  91.     int b;
  92.     int c;
  93.     int d;
  94.     int e;
  95.     int f;
  96.     int g;
  97.     int h;
  98.     int i;
  99.     int j;
  100.     int k;
  101.     int l;
  102.     int a2;
  103.     int b2;
  104.     int c2;
  105.     int d2;
  106.     int e2;
  107.     int f2;
  108.     int g2;
  109.     int h2;
  110.     int i2;
  111.     int j2;
  112.     int k2;
  113.     int l2;
  114.     int z;
  115. };
  116.  
  117. Mensaje * mensaje;
  118.  
  119. // plantilla para liberar con más robustez
  120. template<typename T>
  121. void delete_ptr(T* ptr)
  122. {
  123.     if(ptr)
  124.     {
  125.         delete ptr;
  126.         ptr = NULL;
  127.     }
  128. }
  129.  
  130. // iniciar semaforo compartido (solo el proceso padre)
  131. int set_semvalue(void)
  132. {
  133.     union semun sem_union;
  134.  
  135.     sem_union.val = 1;
  136.     if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);
  137.     return(1);
  138. }
  139.  
  140. // liberar semaforo compartido (solo el proceso padre)
  141. void del_semvalue(void)
  142. {
  143.     union semun sem_union;
  144.    
  145.     if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
  146.         fprintf(stderr, "Failed to delete semaphore\n");
  147. }
  148.  
  149. // intenta bloquear el semaforo compartido
  150. bool lock(void)
  151. {
  152.     bool retorno = false;
  153.  
  154.     struct sembuf sem_b;
  155.    
  156.     sem_b.sem_num = 0;
  157.     sem_b.sem_op = -1; /* P() */
  158.     sem_b.sem_flg = SEM_UNDO;
  159.     if (semop(sem_id, &sem_b, 1) == -1) {
  160.         //fprintf(stderr, "semaphore_p failed\n");
  161.         retorno = false;
  162.     }
  163.     else
  164.         retorno = true;
  165.    
  166.     return retorno;
  167. }
  168.  
  169. // intenta liberar el semaforo compartido
  170. bool unlock(void)
  171. {
  172.     bool retorno = false;
  173.  
  174.     struct sembuf sem_b;
  175.    
  176.     sem_b.sem_num = 0;
  177.     sem_b.sem_op = 1; /* V() */
  178.     sem_b.sem_flg = SEM_UNDO;
  179.     if (semop(sem_id, &sem_b, 1) == -1) {
  180.         //fprintf(stderr, "semaphore_v failed\n");
  181.         retorno = false;
  182.     }
  183.     else
  184.         retorno = true;
  185.        
  186.     return retorno;
  187. }
  188.  
  189. // El proceso padre crea la memoria compartida y el semaforo
  190. void inicial()
  191. {
  192.     id_heap = shmget (key_shared, sizeof(int)*100, 0777 | IPC_CREAT);
  193.     if (id_heap == -1)
  194.     {
  195.         std::cout << "No consigo Id para memoria compartida" << std::endl;
  196.         exit (0);
  197.     }
  198.  
  199.     mini_heap = (int *)shmat (id_heap, (char *)0, 0);
  200.     if (mini_heap == NULL)
  201.     {
  202.         std::cout << "No consigo memoria compartida" << std::endl;
  203.         exit (0);
  204.     }
  205.    
  206.     std::cout << "Memoria compartida creada" << std::endl;
  207.    
  208.     ///////// SEMAFORO
  209.    
  210.     sem_id = semget(key_shared, 1, 0777 | IPC_CREAT);
  211.    
  212.     if(!set_semvalue())
  213.     {
  214.         std::cout << "Error al iniciar semáforo" << std::endl;
  215.         exit (0);
  216.     }
  217.    
  218.     ////////////////////
  219.    
  220.     // Memoria dinamica local
  221.     mensaje = new Mensaje();
  222.     mensaje->z = 0;
  223.    
  224.     // copiar a zona compartida
  225.     memcpy (mini_heap, mensaje, sizeof(*mensaje));
  226.    
  227.     // liberamos la copia local
  228.     delete_ptr(mensaje);
  229. }
  230.  
  231. // el proceso padre libera las zonas compartidas
  232. void final()
  233. {
  234.     int estadoHijo;
  235.    
  236.     for(int i=0 ; i<4; i++)
  237.     {
  238.         wait (&estadoHijo);
  239.  
  240.         if (WIFEXITED(estadoHijo) != 0)
  241.         {
  242.             assert(101 <= WEXITSTATUS(estadoHijo) && WEXITSTATUS(estadoHijo) <= 104);
  243.             //printf ("Padre : Mi hijo ha salido. Devuelve %d\n", WEXITSTATUS(estadoHijo));
  244.         }
  245.     }
  246.     /////////////////////////////////////////////////////////
  247.    
  248.     mensaje = reinterpret_cast<Mensaje*>(mini_heap);
  249.     std::cout << "mensaje->z = " << mensaje->z << std::endl;
  250.    
  251.     // se espera 10000
  252.     assert(mensaje->z == 10000);
  253.    
  254.     //////////////////////////////////////////////////////////
  255.    
  256.     del_semvalue();
  257.    
  258.     //////////////////////////////////////////////////////////
  259.     // liberamos memoria compartida
  260.     shmdt ((char *)mini_heap);
  261.     shmctl (id_heap, IPC_RMID, (struct shmid_ds *)NULL);
  262.    
  263.     std::cout << "Memoria compartida liberada" << std::endl;
  264. }
  265.  
  266. // los procesos hijos se asocian a la zona compartida y a su semaforo
  267. void inicia_proceso_hijo()
  268. {
  269.     std::cout << "Asociandose a la memoria compartida" << std::endl;
  270.  
  271.     id_heap = shmget (key_shared, sizeof(int)*100, 0777 );
  272.     if (id_heap == -1)
  273.     {
  274.         std::cout << "No consigo Id para memoria compartida" << std::endl;
  275.         exit (0);
  276.     }
  277.  
  278.     mini_heap = (int *)shmat (id_heap, (char *)0, 0);
  279.     if (mini_heap == NULL)
  280.     {
  281.         std::cout << "No consigo memoria compartida" << std::endl;
  282.         exit (0);
  283.     }
  284.    
  285.     //////////////////////////////////////////////////////
  286.    
  287.     // asociarse al semaforo ya creado
  288.     sem_id = semget(key_shared, 1, 0777);
  289. }
  290.  
  291. // Los procesos hijso se desasocian de la memoria compartida al salir.
  292. void termina_proceso_hijo()
  293. {
  294.     std::cout << "Desasociandose a la memoria compartida" << std::endl;
  295.     if (id_heap != -1)
  296.         shmdt ((char *)mini_heap);
  297. }
  298.  
  299. // P2
  300. void proceso2()
  301. {
  302.     mensaje = reinterpret_cast<Mensaje*>(mini_heap);
  303.    
  304.     int i=0;
  305.     while( i<10000 )
  306.     {
  307.         if(lock())
  308.         {
  309.             mensaje->z++;
  310.             unlock();
  311.             i++;
  312.         }
  313.         //sleep(0.5);
  314.     }
  315. }
  316.  
  317. // P3
  318. void proceso3()
  319. {
  320.     mensaje = reinterpret_cast<Mensaje*>(mini_heap);
  321.    
  322.     int i=0;
  323.     while( i<10000 )
  324.     {
  325.         if(lock())
  326.         {
  327.             mensaje->z++;
  328.             unlock();
  329.             i++;
  330.         }
  331.         //sleep(0.5);
  332.     }
  333. }
  334.  
  335. // P4
  336. void proceso4()
  337. {
  338.     mensaje = reinterpret_cast<Mensaje*>(mini_heap);
  339.    
  340.     int i=0;
  341.     while( i<10000 )
  342.     {
  343.         if(lock())
  344.         {
  345.             mensaje->z--;
  346.             unlock();
  347.             i++;
  348.         }
  349.         //sleep(0.5);
  350.     }
  351. }
  352.  
  353. /*
  354.  * FIXME: Lo suyo es hacer los fork() con un for(;;) en función del
  355.  * número de cores, que se sabe facilmente con OpenMP:
  356.  *
  357.  *  num_cores = omp_get_num_procs();
  358.     max_threads = omp_get_max_threads();
  359.  *
  360.  */
  361. int main()
  362. {
  363.     key_shared = ftok ("/bin/ls", 33);
  364.     if (key_shared == -1)
  365.     {
  366.         std::cout << "No consigo clave para memoria compartida" << std::endl;
  367.         exit(0);
  368.     }
  369.    
  370.     pid_hijo1 = fork();
  371.     if (pid_hijo1 > 0)
  372.     {      
  373.         inicial();
  374.        
  375.         pid_hijo2 = fork();
  376.         if(pid_hijo2 > 0)
  377.         {
  378.             pid_hijo3 = fork();
  379.             if(pid_hijo3 > 0)
  380.             {
  381.                 pid_hijo4 = fork();
  382.                 if(pid_hijo4 > 0)
  383.                 {
  384.                     // para hacer más procesos secuencialmente
  385.                 }
  386.                 else
  387.                 {
  388.                     inicia_proceso_hijo();
  389.                     proceso4();
  390.                     termina_proceso_hijo();
  391.                     exit (104);    
  392.                 }
  393.             }
  394.             else
  395.             {
  396.                 inicia_proceso_hijo();
  397.                 proceso3();
  398.                 termina_proceso_hijo();
  399.                 exit (103);
  400.             }
  401.         }
  402.         else
  403.         {
  404.             inicia_proceso_hijo();
  405.             proceso2();
  406.             termina_proceso_hijo();
  407.             exit (102);
  408.         }
  409.        
  410.         final();
  411.     }
  412.     else
  413.     {
  414.         exit (101);
  415.     }
  416.    
  417.     return 0;
  418. }
RAW Paste Data
Top