Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cstring>
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <sys/shm.h>
- #include <sys/types.h>
- #include <sys/ipc.h>
- #include <sys/sem.h>
- #include <wait.h>
- #include <assert.h>
- /*
- * Diagrama de precedencia:
- *
- * inicial()
- * |
- * |
- * /|\
- * / | \
- * / | \
- * / | \
- * / | \
- * P1 P2 P3
- * \ | /
- * \ | /
- * \ | /
- * \ | /
- * \|/
- * |
- * |
- * final()
- *
- */
- union semun {
- int val; /* value for SETVAL */
- struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
- unsigned short int *array; /* array for GETALL, SETALL */
- struct seminfo *__buf; /* buffer for IPC_INFO */
- };
- pid_t pid_hijo1;
- pid_t pid_hijo2;
- pid_t pid_hijo3;
- pid_t pid_hijo4;
- key_t key_shared;
- int id_heap;
- int *mini_heap = NULL;
- int sem_id;
- // Estructura de 100 bytes
- class Mensaje
- {
- public:
- Mensaje()
- {
- a = 0;
- b = 0;
- c = 0;
- d = 0;
- e = 0;
- f = 0;
- g = 0;
- h = 0;
- i = 0;
- j = 0;
- k = 0;
- l = 0;
- a2 = 0;
- b2 = 0;
- c2 = 0;
- d2 = 0;
- e2 = 0;
- f2 = 0;
- g2 = 0;
- h2 = 0;
- i2 = 0;
- j2 = 0;
- k2 = 0;
- l2 = 0;
- z = 0;
- }
- int a;
- int b;
- int c;
- int d;
- int e;
- int f;
- int g;
- int h;
- int i;
- int j;
- int k;
- int l;
- int a2;
- int b2;
- int c2;
- int d2;
- int e2;
- int f2;
- int g2;
- int h2;
- int i2;
- int j2;
- int k2;
- int l2;
- int z;
- };
- Mensaje * mensaje;
- // plantilla para liberar con más robustez
- template<typename T>
- void delete_ptr(T* ptr)
- {
- if(ptr)
- {
- delete ptr;
- ptr = NULL;
- }
- }
- // iniciar semaforo compartido (solo el proceso padre)
- int set_semvalue(void)
- {
- union semun sem_union;
- sem_union.val = 1;
- if (semctl(sem_id, 0, SETVAL, sem_union) == -1) return(0);
- return(1);
- }
- // liberar semaforo compartido (solo el proceso padre)
- void del_semvalue(void)
- {
- union semun sem_union;
- if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
- fprintf(stderr, "Failed to delete semaphore\n");
- }
- // intenta bloquear el semaforo compartido
- bool lock(void)
- {
- bool retorno = false;
- struct sembuf sem_b;
- sem_b.sem_num = 0;
- sem_b.sem_op = -1; /* P() */
- sem_b.sem_flg = SEM_UNDO;
- if (semop(sem_id, &sem_b, 1) == -1) {
- //fprintf(stderr, "semaphore_p failed\n");
- retorno = false;
- }
- else
- retorno = true;
- return retorno;
- }
- // intenta liberar el semaforo compartido
- bool unlock(void)
- {
- bool retorno = false;
- struct sembuf sem_b;
- sem_b.sem_num = 0;
- sem_b.sem_op = 1; /* V() */
- sem_b.sem_flg = SEM_UNDO;
- if (semop(sem_id, &sem_b, 1) == -1) {
- //fprintf(stderr, "semaphore_v failed\n");
- retorno = false;
- }
- else
- retorno = true;
- return retorno;
- }
- // El proceso padre crea la memoria compartida y el semaforo
- void inicial()
- {
- id_heap = shmget (key_shared, sizeof(int)*100, 0777 | IPC_CREAT);
- if (id_heap == -1)
- {
- std::cout << "No consigo Id para memoria compartida" << std::endl;
- exit (0);
- }
- mini_heap = (int *)shmat (id_heap, (char *)0, 0);
- if (mini_heap == NULL)
- {
- std::cout << "No consigo memoria compartida" << std::endl;
- exit (0);
- }
- std::cout << "Memoria compartida creada" << std::endl;
- ///////// SEMAFORO
- sem_id = semget(key_shared, 1, 0777 | IPC_CREAT);
- if(!set_semvalue())
- {
- std::cout << "Error al iniciar semáforo" << std::endl;
- exit (0);
- }
- ////////////////////
- // Memoria dinamica local
- mensaje = new Mensaje();
- mensaje->z = 0;
- // copiar a zona compartida
- memcpy (mini_heap, mensaje, sizeof(*mensaje));
- // liberamos la copia local
- delete_ptr(mensaje);
- }
- // el proceso padre libera las zonas compartidas
- void final()
- {
- int estadoHijo;
- for(int i=0 ; i<4; i++)
- {
- wait (&estadoHijo);
- if (WIFEXITED(estadoHijo) != 0)
- {
- assert(101 <= WEXITSTATUS(estadoHijo) && WEXITSTATUS(estadoHijo) <= 104);
- //printf ("Padre : Mi hijo ha salido. Devuelve %d\n", WEXITSTATUS(estadoHijo));
- }
- }
- /////////////////////////////////////////////////////////
- mensaje = reinterpret_cast<Mensaje*>(mini_heap);
- std::cout << "mensaje->z = " << mensaje->z << std::endl;
- // se espera 10000
- assert(mensaje->z == 10000);
- //////////////////////////////////////////////////////////
- del_semvalue();
- //////////////////////////////////////////////////////////
- // liberamos memoria compartida
- shmdt ((char *)mini_heap);
- shmctl (id_heap, IPC_RMID, (struct shmid_ds *)NULL);
- std::cout << "Memoria compartida liberada" << std::endl;
- }
- // los procesos hijos se asocian a la zona compartida y a su semaforo
- void inicia_proceso_hijo()
- {
- std::cout << "Asociandose a la memoria compartida" << std::endl;
- id_heap = shmget (key_shared, sizeof(int)*100, 0777 );
- if (id_heap == -1)
- {
- std::cout << "No consigo Id para memoria compartida" << std::endl;
- exit (0);
- }
- mini_heap = (int *)shmat (id_heap, (char *)0, 0);
- if (mini_heap == NULL)
- {
- std::cout << "No consigo memoria compartida" << std::endl;
- exit (0);
- }
- //////////////////////////////////////////////////////
- // asociarse al semaforo ya creado
- sem_id = semget(key_shared, 1, 0777);
- }
- // Los procesos hijso se desasocian de la memoria compartida al salir.
- void termina_proceso_hijo()
- {
- std::cout << "Desasociandose a la memoria compartida" << std::endl;
- if (id_heap != -1)
- shmdt ((char *)mini_heap);
- }
- // P2
- void proceso2()
- {
- mensaje = reinterpret_cast<Mensaje*>(mini_heap);
- int i=0;
- while( i<10000 )
- {
- if(lock())
- {
- mensaje->z++;
- unlock();
- i++;
- }
- //sleep(0.5);
- }
- }
- // P3
- void proceso3()
- {
- mensaje = reinterpret_cast<Mensaje*>(mini_heap);
- int i=0;
- while( i<10000 )
- {
- if(lock())
- {
- mensaje->z++;
- unlock();
- i++;
- }
- //sleep(0.5);
- }
- }
- // P4
- void proceso4()
- {
- mensaje = reinterpret_cast<Mensaje*>(mini_heap);
- int i=0;
- while( i<10000 )
- {
- if(lock())
- {
- mensaje->z--;
- unlock();
- i++;
- }
- //sleep(0.5);
- }
- }
- /*
- * FIXME: Lo suyo es hacer los fork() con un for(;;) en función del
- * número de cores, que se sabe facilmente con OpenMP:
- *
- * num_cores = omp_get_num_procs();
- max_threads = omp_get_max_threads();
- *
- */
- int main()
- {
- key_shared = ftok ("/bin/ls", 33);
- if (key_shared == -1)
- {
- std::cout << "No consigo clave para memoria compartida" << std::endl;
- exit(0);
- }
- pid_hijo1 = fork();
- if (pid_hijo1 > 0)
- {
- inicial();
- pid_hijo2 = fork();
- if(pid_hijo2 > 0)
- {
- pid_hijo3 = fork();
- if(pid_hijo3 > 0)
- {
- pid_hijo4 = fork();
- if(pid_hijo4 > 0)
- {
- // para hacer más procesos secuencialmente
- }
- else
- {
- inicia_proceso_hijo();
- proceso4();
- termina_proceso_hijo();
- exit (104);
- }
- }
- else
- {
- inicia_proceso_hijo();
- proceso3();
- termina_proceso_hijo();
- exit (103);
- }
- }
- else
- {
- inicia_proceso_hijo();
- proceso2();
- termina_proceso_hijo();
- exit (102);
- }
- final();
- }
- else
- {
- exit (101);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement