Guest User

Ricardo

a guest
Aug 30th, 2010
356
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

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×