]> git.llucax.com Git - z.facultad/75.74/practicos.git/blob - practicas/practica2/P02e2111.cpp
Mejora el setup de IPC.
[z.facultad/75.74/practicos.git] / practicas / practica2 / P02e2111.cpp
1 /**
2  * Leandro Lucarella (77891)
3  *
4  * Ejercicio 2.1.1. Implementa productor-consumidor con semaforos binarios y
5  * shared memory.
6  */
7
8 #include <iostream>
9 #include <cstdlib>
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <sys/types.h>
13 #include <sys/ipc.h>
14 #include <sys/shm.h>
15 #include <sys/sem.h>
16
17 /// Clave de nuestro segmento shm y semaforo
18 #define SHM_KEY 0x77891220
19 #define SEM_KEY 0x77891221
20
21 /// Elemento a producir/consumir
22 typedef int Elemento;
23
24 /// Nombres de los semaforos a utilizar
25 enum sem_num_t { MUTEX, FULL, EMPTY };
26
27 /// Nombres de los procesos
28 enum proc_t { PRODUCTOR, CONSUMIDOR };
29
30 /// Hace un wait (P) al semaforo (devuelve false si hubo error).
31 void sem_wait(int sem_id, sem_num_t sem_num)
32 {
33         struct sembuf op;
34         op.sem_op = -1; // sacar 1
35         op.sem_num = sem_num; // al semaforo sem_num
36         op.sem_flg = 0; // esperando
37         if (semop(sem_id, &op, 1) > 0)
38         {
39                 std::cerr << "No se pudo sacar al semaforo.\n";
40                 exit(100);
41         }
42 }
43
44 /// Hace un signal (V) al semaforo (devuelve false si hubo error).
45 void sem_signal(int sem_id, sem_num_t sem_num)
46 {
47         struct sembuf op;
48         op.sem_op =  1; // agregar 1
49         op.sem_num = sem_num; // al semaforo sem_num
50         op.sem_flg = 0; // esperando
51         if (semop(sem_id, &op, 1) > 0)
52         {
53                 std::cerr << "No se pudo poner al semaforo.\n";
54                 exit(101);
55         }
56 }
57
58 int main(int argc, char *argv[])
59 {
60         using std::cerr;
61         using std::cout;
62
63         if (argc < 2)
64         {
65                 cerr << "Faltan parametros: " << argv[0] << " N [max_iter]\n";
66                 return 1;
67         }
68         proc_t proc = (proc_t) atoi(argv[1]);
69
70         // Shared memory
71         int shm_id = shmget(SHM_KEY, sizeof(Elemento), IPC_CREAT | 0666);
72         if (shm_id == -1)
73         {
74                 cerr << "Error al crea/obtener shared memory.\n";
75                 return 2;
76         }
77         Elemento* elem = (Elemento*) shmat(shm_id, NULL, 0);
78         if (elem == (Elemento*) -1)
79         {
80                 cerr << "Error al attachear shared memory.\n";
81                 return 3;
82         }
83         cout << "Shared memory id = " << shm_id << "\n";
84
85         // Semaforos
86         int sem_id = semget(SEM_KEY, 3, 0666 | IPC_CREAT);
87         if (sem_id == -1)
88         {
89                 cerr << "Error al crea/obtener semaforos.\n";
90                 return 4;
91         }
92         // Si somos los primeros inicializamos
93         if (!proc)
94         {
95                 if (semctl(sem_id, MUTEX, SETVAL, 1) < 0)
96                 {
97                         cerr << "No se pudo inicializar semaforo.\n";
98                         return 5;
99                 }
100                 if (semctl(sem_id, FULL, SETVAL, 0) < 0)
101                 {
102                         cerr << "No se pudo inicializar semaforo.\n";
103                         return 6;
104                 }
105                 if (semctl(sem_id, EMPTY, SETVAL, 1) < 0)
106                 {
107                         cerr << "No se pudo inicializar semaforo.\n";
108                         return 7;
109                 }
110                 cout << "Semaforos inicializados id = " << sem_id << "\n";
111         }
112         else // Si soy otro espero un poco por las dudas para que corra el 1ro
113         {
114                 usleep(1000);
115         }
116
117         // Maxima cantidad de iteraciones (puede venir por parametro)
118         int max_iter = 10;
119         if (argc > 2)
120                 max_iter = atoi(argv[2]);
121
122         // Loop principal
123         for (int i = 0; i < max_iter; ++i)
124         {
125                 int val = rand();
126                 // espera que este lleno/vacio segun sea consumidor/productor
127                 if (proc == PRODUCTOR)
128                         sem_wait(sem_id, EMPTY);
129                 else
130                         sem_wait(sem_id, FULL);
131                 sem_wait(sem_id, MUTEX); // lock
132                 // produzco / consumo
133                 if (proc == PRODUCTOR)
134                         *elem = val;
135                 else
136                         val = *elem;
137                 sem_signal(sem_id, MUTEX); // unlock
138                 // indica que esta lleno/vacio segun sea productor/consumidor
139                 if (proc == PRODUCTOR)
140                 {
141                         cout << "Productor (" << getpid() << ") puso elem = "
142                                 << val << std::endl;
143                         sem_signal(sem_id, FULL);
144                 }
145                 else
146                 {
147                         cout << "Consumidor (" << getpid() << ") saco elem = "
148                                 << val << std::endl;
149                         sem_signal(sem_id, EMPTY);
150                 }
151         }
152
153         if (shmdt(elem) == -1)
154         {
155                 cerr << "Error al detachear shared memory.\n";
156                 return -1;
157         }
158
159         return 0;
160 }