Solución - Programación Concurrente y Tiempo Real

Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
Prueba de Laboratorio [Solución]
Modelo B01 – Semáforos y Memoria Compartida
APELLIDOS: ___________________________________________________________________
NOMBRE:
_____________________________ GRUPO DE LABORATORIO: __________
Indicaciones:
●
●
●
●
Calificación
No se permiten libros, apuntes ni teléfonos móviles.
Cuando tenga una solución al ejercicio (compilación + ejecución) muéstrela al profesor.
Debe anotar su solución por escrito en el espacio disponible en este cuestionario.
Tiempo para realizar la prueba: 90 minutos.
Enunciado
Construya, utilizando ANSI C estándar, tres ejecutables que modelen el siguiente sistema. La simulación
constará de un proceso manager que cargará una cadena de la línea de órdenes y encargará su traducción a
un conjunto de procesos decoder. El usuario ejecutará un proceso manager indicándole tres argumentos:
./exec/manager <cadena> <num_proc_decoder> <tam_max_tarea>
Este proceso manager cargará cadena en un array de caracteres empleando el punto como separador de
elementos. Esta cadena estará formada por números enteros (entre 1 y 57) que tendrán que traducir a
caracteres los procesos decoder (con ayuda del proceso symbol_decoder). En num_proc_decoder se indicará
el número de procesos decoder que se lanzarán para traducir el array y tam_max_tarea será el tamaño
máximo de cada tarea o subvector (cada proceso decoder traducirá del array original suministrado por el
manager un máximo de n_tasks tareas). La correspondencia de traducción se resume en la siguiente tabla (la
última fila de la tabla es la correspondencia del carácter con su código ASCII necesario para realizar la
traducción):
Entero
1
2
...
25
26
27
28
...
51
52
53
54
55
56
57
Traducción
a
b
...
y
z
A
B
...
Y
Z
.
,
!
?
_
Código ASCII
97
98
...
121
122
65
66
...
89
90
46
44
33
63
95
El sistema contará con un único proceso symbol_decoder que se encargará de traducir los símbolos de
puntuación que se corresponden con los valores enteros del 53 al 57 inclusive. Así, cuando un proceso
decoder encuentre uno de estos valores, 'despertará' al proceso symbol_decoder que escribirá en una variable
de memoria compartida el resultado de traducir ese signo de puntuación, volviendo a 'dormir' después de
realizar su trabajo. El proceso decoder leerá ese valor y lo usará como resultado de la traducción final.
Los procesos decoder atenderán peticiones de traducción hasta que el manager les envíe la señal de
terminación. En cada petición el proceso manager les indicará el índice de inicio y fin de cada tarea
(subvector). Los procesos decoder actualizarán directamente el resultado en el array creado por el manager.
Por ejemplo, ante una ejecución como:
./exec/manager 34.5.12.12.15.55 2 2
el proceso manager lanzará dos procesos decoder que traducirán la cadena de entrada (3 tareas de tamaño 2).
El resultado de la traducción será el siguiente array de salida en ASCII, con representación en cadena de
caracteres "Hello!":
Array de entrada
34
5
12
12
15
55
Array de salida (ASCII)
72
101
108
108
111
33
Representación como caracteres
'H'
'e'
'l'
'l'
'o'
'!'
Página 1 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
Resolución
Utilice el código fuente suministrado a continuación como plantilla para resolver el ejercicio. Este código no debe ser
modificado (salvo la inicialización de los semáforos en el proceso manager). Únicamente debe incorporar su código en
la sección indicada. No realice comprobación de errores en los parámetros. El proceso manager se encarga de enviar la
señal de terminación a los procesos decoder y al proceso symbol_decoder cuando éstos han calculado el resultado final.
Preste especial atención a lograr el máximo paralelismo posible en la solución.
 Indique a continuación el valor de inicialización de los semáforos (código en manager.c):
Línea Código
Semáforo
Uso
Valor inicial
344
SEM_TASK_READY
Nueva orden; despierta a un proceso decoder
0
345
SEM_TASK_READ
Indica al manager que la orden fue leída
0
346
SEM_TASK_PROCESSED
La traducción de una tarea fue realizada
0
348
SEM_MUTEX
Uso exclusivo del proceso symbol_decoder
1
349
SEM_SYMBOL_READY
Despierta al proceso symbol_decoder
0
350
SEM_SYMBOL_DECODED
Espera fin del proceso symbol_decoder
0
Test de Resultado Correcto
Una vez resuelto el ejercicio, si ejecuta el manager con los siguientes argumentos (make test),
./exec/manager 34.5.12.12.15.55 2 2
el resultado debe ser algo similar a (naturalmente cambiará el PID de los procesos decoder y probablemente
el orden de atención de las peticiones):
./exec/manager 34.5.12.12.15.55 2 2 [PID 11997] Begin 0 End 1 Decoded Task He
[PID 11998] Begin 2 End 3 Decoded Task ll
[PID 11997] Begin 4 End 5 Decoded Task o!
Decoded result: Hello!
 Complete el resultado obtenido de la ejecución con la siguiente lista de argumentos (make solution):
./exec/manager 35.57.18.5.1.12.12.25.57.12.9.11.5.57.20.8.9.19.57.20.5.19.20.55 5 4
Decoded result: I_really_like_this_test!
Página 2 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
Esqueleto de Código Fuente
A continuación se muestra el esqueleto de código fuente para resolver el ejercicio. Sólo debe modificar la
inicialización de los semáforos e incluir la parte que falta del proceso decoder y el proceso symbol_decoder.
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
DIROBJ := obj/
DIREXE := exec/
DIRHEA := include/
DIRSRC := src/
CFLAGS := ­I$(DIRHEA) ­c ­Wall ­std=c99
LDLIBS := ­pthread ­lrt ­lm
CC := gcc
all : dirs manager decoder symbol_decoder
dirs:
mkdir ­p $(DIROBJ) $(DIREXE)
manager: $(DIROBJ)manager.o $(DIROBJ)semaphoreI.o $(CC) ­lm ­o $(DIREXE)$@ $^ $(LDLIBS)
decoder: $(DIROBJ)decoder.o $(DIROBJ)semaphoreI.o $(CC) ­o $(DIREXE)$@ $^ $(LDLIBS)
symbol_decoder: $(DIROBJ)symbol_decoder.o $(DIROBJ)semaphoreI.o $(CC) ­o $(DIREXE)$@ $^ $(LDLIBS)
$(DIROBJ)%.o: $(DIRSRC)%.c
$(CC) $(CFLAGS) $^ ­o $@
test:
./exec/manager 34.5.12.12.15.55 2 2
solution:
./exec/manager 35.57.18.5.1.12.12.25.57.12.9.11.5.57.20.8.9.19.57.20.5.19.20.55 5 4
clean : rm ­rf *~ core $(DIROBJ) $(DIREXE) $(DIRHEA)*~ $(DIRSRC)*~
definitions.h
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#define SEM_TASK_READY "sem_task_ready"
#define SEM_TASK_READ "sem_task_read"
#define SEM_TASK_PROCESSED "sem_task_processed"
#define SHM_TASK "shm_task"
#define SHM_DATA "shm_data"
#define SEM_MUTEX "sem_mutex"
#define SEM_SYMBOL_READY "sem_symbol_ready"
#define SEM_SYMBOL_DECODED "sem_symbol_decoded"
#define SHM_SYMBOL "shm_symbol"
#define DECODER_CLASS "DECODER"
#define DECODER_PATH "./exec/decoder"
#define SYMBOL_DECODER_CLASS "SYMBOL_DECODER"
#define SYMBOL_DECODER_PATH "./exec/symbol_decoder"
#define MAX_ARRAY_SIZE 1000
#define NUM_SYMBOL_DECODERS 1
#define SEPARATOR "."
#define TRUE 1
#define FALSE 0
struct TData_t {
char vector[MAX_ARRAY_SIZE];
};
struct TTask_t {
int begin;
int end;
};
struct TSymbol_t {
char value;
};
enum ProcessClass_t {DECODER, SYMBOL_DECODER}; struct TProcess_t { enum ProcessClass_t class; /* DECODER or SYMBOL_DECODER */
pid_t pid; /* Process ID */
char *str_process_class; /* String representation of the process class */
};
Página 3 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
semaphoreI.h
77
78
79
80
81
82
83
84
85
86
87
88
#ifndef __SEMAPHOREI_H__
#define __SEMAPHOREI_H__
#include <semaphore.h>
sem_t *create_semaphore (const char *name, unsigned int value);
sem_t *get_semaphore (const char *name);
void remove_semaphore (const char *name);
void signal_semaphore (sem_t *sem);
void wait_semaphore (sem_t *sem);
#endif
semaphoreI.c
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphoreI.h>
sem_t *create_semaphore (const char *name, unsigned int value) {
sem_t *sem;
if ((sem = sem_open(name, O_CREAT, 0644, value)) == SEM_FAILED) {
fprintf(stderr, "Error creating semaphore <%s>: %s\n", name, strerror(errno));
exit(EXIT_FAILURE);
}
return sem;
}
sem_t *get_semaphore (const char *name) {
sem_t *sem;
if ((sem = sem_open(name, O_RDWR)) == SEM_FAILED) {
fprintf(stderr, "Error retrieving semaphore <%s>: %s\n", name, strerror(errno));
exit(EXIT_FAILURE);
}
return sem;
}
void remove_semaphore (const char *name) {
sem_t *sem = get_semaphore(name);
if ((sem_close(sem)) == ­1) {
fprintf(stderr, "Error closing semaphore <%s>: %s\n", name, strerror(errno));
exit(EXIT_FAILURE);
}
if ((sem_unlink(name)) == ­1) {
fprintf(stderr, "Error removing semaphore <%s>: %s\n", name, strerror(errno));
exit(EXIT_FAILURE);
}
}
void signal_semaphore (sem_t *sem) {
if ((sem_post(sem)) == ­1) {
fprintf(stderr, "Error incrementing the semaphore: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
}
void wait_semaphore (sem_t *sem) {
if ((sem_wait(sem)) == ­1) {
fprintf(stderr, "Error decrementing the semaphore: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
}
Página 4 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
manager.c
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#define _POSIX_SOURCE
#define _BSD_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <linux/limits.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <definitions.h>
#include <semaphoreI.h>
/* Total number of processes */
int g_nProcesses;
/* 'Process table' (child processes) */
struct TProcess_t *g_process_table;
/* Process management */
void create_processes_by_class(enum ProcessClass_t class, int n_processes, int index_process_table);
pid_t create_single_process(const char *class, const char *path, const char *argv);
void get_str_process_info(enum ProcessClass_t class, char **path, char **str_process_class);
void init_process_table(int n_decoders, int n_symbol_decoders);
void terminate_processes();
/* Semaphores and shared memory management */
void create_shm_segments(int *shm_data, int *shm_task, int *shm_symbol, struct TData_t **p_data, struct TTask_t **p_task, char *encoded_input_data, int *n_input_data);
void create_sems(sem_t **p_sem_task_ready, sem_t **p_sem_task_read, sem_t **p_sem_task_processed);
void close_shared_memory_segments(int shm_data, int shm_task, int shm_symbol);
/* Task management */
void notify_tasks(sem_t *sem_task_ready, sem_t *sem_task_read, struct TTask_t *task,
int max_task_size, int *n_tasks, int n_input_data);
void wait_tasks_termination(sem_t *sem_task_processed, int n_tasks);
/* Auxiliar functions */
void free_resources();
void install_signal_handler();
void parse_argv(int argc, char *argv[], char **p_encoded_input_data, int *n_decoders, int *max_task_size);
void print_result(struct TData_t *data, int n_input_data);
void signal_handler(int signo);
/******************** Main function ********************/
int main(int argc, char *argv[]) {
struct TData_t *data;
struct TTask_t *task;
int shm_data, shm_task, shm_symbol;
sem_t *sem_task_ready, *sem_task_read, *sem_task_processed;
char *encoded_input_data;
int n_decoders, max_task_size, n_input_data, n_tasks;
/* Install signal handler and parse arguments*/
install_signal_handler();
parse_argv(argc, argv, &encoded_input_data, &n_decoders, &max_task_size);
/* Init the process table*/
init_process_table(n_decoders, NUM_SYMBOL_DECODERS);
/* Create shared memory segments and semaphores */
create_shm_segments(&shm_data, &shm_task, &shm_symbol, &data, &task, encoded_input_data, &n_input_data);
create_sems(&sem_task_ready, &sem_task_read, &sem_task_processed);
/* Create processes */
create_processes_by_class(DECODER, n_decoders, 0);
create_processes_by_class(SYMBOL_DECODER, NUM_SYMBOL_DECODERS, n_decoders);
/* Manage tasks */
notify_tasks(sem_task_ready, sem_task_read, task, max_task_size, &n_tasks,n_input_data);
wait_tasks_termination(sem_task_processed, n_tasks);
/* Print the decoded text */
print_result (data, n_input_data);
Página 5 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/* Free resources and terminate */
close_shared_memory_segments(shm_data, shm_task, shm_symbol);
terminate_processes();
free_resources();
return EXIT_SUCCESS;
}
/******************** Process Management ********************/
void create_processes_by_class(enum ProcessClass_t class, int n_processes, int index_process_table) {
char *path = NULL, *str_process_class = NULL;
int i;
pid_t pid;
get_str_process_info(class, &path, &str_process_class);
for (i = index_process_table; i < (index_process_table + n_processes); i++) {
pid = create_single_process(path, str_process_class, NULL);
g_process_table[i].class = class;
g_process_table[i].pid = pid;
g_process_table[i].str_process_class = str_process_class;
}
printf("[MANAGER] %d %s processes created.\n", n_processes, str_process_class);
sleep(1);
}
pid_t create_single_process(const char *path, const char *class, const char *argv) {
pid_t pid;
switch (pid = fork()) {
case ­1 :
fprintf(stderr, "[MANAGER] Error creating %s process: %s.\n", class, strerror(errno));
terminate_processes();
free_resources();
exit(EXIT_FAILURE);
/* Child process */
case 0 : if (execl(path, class, argv, NULL) == ­1) {
fprintf(stderr, "[MANAGER] Error using execl() in %s process: %s.\n", class, strerror(errno));
exit(EXIT_FAILURE);
}
}
/* Child PID */
return pid;
}
void get_str_process_info(enum ProcessClass_t class, char **path, char **str_process_class) {
switch (class) {
case DECODER:
*path = DECODER_PATH;
*str_process_class = DECODER_CLASS;
break;
case SYMBOL_DECODER:
*path = SYMBOL_DECODER_PATH;
*str_process_class = SYMBOL_DECODER_CLASS;
break;
}
}
void init_process_table(int n_decoders, int n_symbol_decoders) {
int i;
/* Number of processes to be created */
g_nProcesses = n_decoders + n_symbol_decoders; /* Allocate memory for the 'process table' */
g_process_table = malloc(g_nProcesses * sizeof(struct TProcess_t)); /* Init the 'process table' */
for (i = 0; i < g_nProcesses; i++) {
g_process_table[i].pid = 0;
}
}
void terminate_processes() {
int i; printf("\n­­­­­ [MANAGER] Terminating running child processes ­­­­­ \n");
for (i = 0; i < g_nProcesses; i++) {
/* Child process alive */
if (g_process_table[i].pid != 0) { printf("[MANAGER] Terminating %s process [%d]...\n", g_process_table[i].str_process_class, g_process_table[i].pid);
if (kill(g_process_table[i].pid, SIGINT) == ­1) {
fprintf(stderr, "[MANAGER] Error using kill() on process %d: %s.\n", g_process_table[i].pid, strerror(errno));
}
}
}
}
Página 6 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
/******************** Semaphores and shared memory management ********************/
void create_shm_segments(int *shm_data, int *shm_task, int *shm_symbol, struct TData_t **p_data, struct TTask_t **p_task, char *encoded_input_data, int *n_input_data) {
int i = 0;
char *encoded_character;
/* Create and initialize shared memory segments */
*shm_data = shm_open(SHM_DATA, O_CREAT | O_RDWR, 0644); ftruncate(*shm_data, sizeof(struct TData_t)); *p_data = mmap(NULL, sizeof(struct TData_t), PROT_READ | PROT_WRITE, MAP_SHARED, *shm_data, 0);
*shm_task = shm_open(SHM_TASK, O_CREAT | O_RDWR, 0644);
ftruncate(*shm_task, sizeof(struct TTask_t));
*p_task = mmap(NULL, sizeof(struct TTask_t), PROT_READ | PROT_WRITE, MAP_SHARED, *shm_task, 0);
*shm_symbol = shm_open(SHM_SYMBOL, O_CREAT | O_RDWR, 0644);
ftruncate(*shm_symbol, sizeof(char));
/* No need to map shm_symbol since the manager process does not use it */
/* Load encoded data */
(*p_data)­>vector[i++] = atoi(strtok(encoded_input_data, SEPARATOR));
while ((encoded_character = strtok(NULL, SEPARATOR)) != NULL) {
(*p_data)­>vector[i++] = atoi(encoded_character);
}
*n_input_data = i;
}
void create_sems(sem_t **p_sem_task_ready, sem_t **p_sem_task_read, sem_t **p_sem_task_processed) { /* Create and initialize semaphores */
*p_sem_task_ready = create_semaphore(SEM_TASK_READY, 0); *p_sem_task_read = create_semaphore(SEM_TASK_READ, 0);
*p_sem_task_processed = create_semaphore(SEM_TASK_PROCESSED, 0);
/* The manager process only initializes the rest, but it does not use them */
create_semaphore(SEM_MUTEX, 1);
create_semaphore(SEM_SYMBOL_READY, 0);
create_semaphore(SEM_SYMBOL_DECODED, 0);
}
void close_shared_memory_segments(int shm_data, int shm_task, int shm_symbol) {
close(shm_data);
close(shm_task);
close(shm_symbol);
}
/******************** Task management ********************/
void notify_tasks(sem_t *sem_task_ready, sem_t *sem_task_read, struct TTask_t *task, int max_task_size, int *n_tasks, int n_input_data) {
int current_task = 0;
/* Number of subvectors */
*n_tasks = ceil(n_input_data / (float)max_task_size);
while (current_task < *n_tasks) {
/* Compute the task info */
task­>begin = current_task * max_task_size;
task­>end = task­>begin + max_task_size ­ 1;
if (task­>end > (n_input_data ­ 1)) {
task­>end = n_input_data ­ 1;
} current_task++;
/* Task notification through rendezvous */
signal_semaphore(sem_task_ready);
wait_semaphore(sem_task_read);
}
}
void wait_tasks_termination(sem_t *sem_task_processed, int n_tasks) {
int n_tasks_processed = 0;
while (n_tasks_processed < n_tasks) {
wait_semaphore(sem_task_processed); n_tasks_processed++; }
}
/******************** Auxiliar functions ********************/
void free_resources() {
printf("\n­­­­­ [MANAGER] Freeing resources ­­­­­ \n");
/* Free the 'process table' memory */
free(g_process_table); /* Semaphores */ remove_semaphore(SEM_TASK_READY);
remove_semaphore(SEM_TASK_READ);
remove_semaphore(SEM_TASK_PROCESSED);
Página 7 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
remove_semaphore(SEM_MUTEX);
remove_semaphore(SEM_SYMBOL_READY);
remove_semaphore(SEM_SYMBOL_DECODED);
/* Shared memory segments*/
shm_unlink(SHM_TASK);
shm_unlink(SHM_DATA);
shm_unlink(SHM_SYMBOL);
}
void install_signal_handler() {
if (signal(SIGINT, signal_handler) == SIG_ERR) {
fprintf(stderr, "[MANAGER] Error installing signal handler: %s.\n", strerror(errno)); exit(EXIT_FAILURE);
}
}
void parse_argv(int argc, char *argv[], char **p_encoded_input_data, int *n_decoders, int *max_task_size) {
if (argc != 4) {
fprintf(stderr, "Synopsis: ./exec/manager <data> <n_decoders> <max_task_size>.\n"); exit(EXIT_FAILURE); }
*p_encoded_input_data = argv[1];
*n_decoders = atoi(argv[2]); *max_task_size = atoi(argv[3]);
}
void print_result(struct TData_t *data, int n_input_data) {
int i;
printf("\n­­­­­ [MANAGER] Printing result ­­­­­ \n");
printf("Decoded result: ");
for (i = 0; i < n_input_data; i++) {
printf("%c", data­>vector[i]); }
printf("\n");
}
void signal_handler(int signo) {
printf("\n[MANAGER] Program termination (Ctrl + C).\n");
terminate_processes();
free_resources();
exit(EXIT_SUCCESS);
}
decoder.c
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <definitions.h>
#include <semaphoreI.h>
/* Semaphores and shared memory retrieval */
void get_shm_segments(int *shm_data, int *shm_task, int *shm_symbol, struct TData_t **p_data, struct TTask_t **p_task, struct TSymbol_t **p_symbol);
void get_sems(sem_t **p_sem_task_ready, sem_t **p_sem_task_read, sem_t **p_sem_task_processed, sem_t **p_sem_mutex, sem_t **p_sem_symbol_ready, sem_t **p_sem_symbol_decoded);
/* Task management */
void get_and_process_task(sem_t *sem_task_ready, sem_t *sem_task_read, sem_t *sem_mutex, sem_t *sem_symbol_ready, sem_t *sem_symbol_decoded, struct TData_t *data, const struct TTask_t *task, struct TSymbol_t *symbol);
void notify_task_completed(sem_t *sem_task_processed);
/******************** Main function ********************/
int main(int argc, char *argv[]) {
struct TData_t *data;
struct TTask_t *task;
struct TSymbol_t *symbol;
int shm_data, shm_task, shm_symbol;
sem_t *sem_task_ready, *sem_task_read, *sem_task_processed;
sem_t *sem_mutex, *sem_symbol_ready, *sem_symbol_decoded;
/* Get shared memory segments and semaphores */
get_shm_segments(&shm_data, &shm_task, &shm_symbol, &data, &task, &symbol);
get_sems(&sem_task_ready, &sem_task_read, &sem_task_processed, &sem_mutex, &sem_symbol_ready, &sem_symbol_decoded);
Página 8 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
/* Will work until killed by the manager */
while (TRUE) {
get_and_process_task(sem_task_ready, sem_task_read, sem_mutex, sem_symbol_ready,
sem_symbol_decoded, data, task, symbol);
notify_task_completed(sem_task_processed);
}
return EXIT_SUCCESS;
}
/******************** Semaphores and shared memory retrieval ********************/
void get_shm_segments(int *shm_data, int *shm_task, int *shm_symbol, struct TData_t **data, struct TTask_t **task,
struct TSymbol_t **symbol) {
*shm_data = shm_open(SHM_DATA, O_RDWR, 0644);
*data = mmap(NULL, sizeof(struct TData_t), PROT_READ | PROT_WRITE, MAP_SHARED, *shm_data, 0);
*shm_task = shm_open(SHM_TASK, O_RDWR, 0644);
*task = mmap(NULL, sizeof(struct TTask_t), PROT_READ | PROT_WRITE, MAP_SHARED, *shm_task, 0);
*shm_symbol = shm_open(SHM_SYMBOL, O_RDWR, 0644);
*symbol = mmap(NULL, sizeof(struct TSymbol_t), PROT_READ | PROT_WRITE, MAP_SHARED, *shm_symbol, 0);
}
void get_sems(sem_t **p_sem_task_ready, sem_t **p_sem_task_read, sem_t **p_sem_task_processed, sem_t **p_sem_mutex, sem_t **p_sem_symbol_ready, sem_t **p_sem_symbol_decoded) {
*p_sem_task_ready = get_semaphore(SEM_TASK_READY);
*p_sem_task_read = get_semaphore(SEM_TASK_READ);
*p_sem_task_processed = get_semaphore(SEM_TASK_PROCESSED);
*p_sem_mutex = get_semaphore(SEM_MUTEX);
*p_sem_symbol_ready = get_semaphore(SEM_SYMBOL_READY);
*p_sem_symbol_decoded = get_semaphore(SEM_SYMBOL_DECODED);
}
/******************** Task management ********************/
void get_and_process_task(sem_t *sem_task_ready, sem_t *sem_task_read, sem_t *sem_mutex, sem_t *sem_symbol_ready, sem_t *sem_symbol_decoded, struct TData_t *data, const struct TTask_t * task, struct TSymbol_t *symbol) {
 Incluya aquí el código de get_and_process_task (Longitud aprox. ≈ 36 Líneas de código)
Muestre en pantalla información sobre el PID del proceso que ha calculado cada subvector, el inicio y el fin y el resultado
parcial de traducción, como en el siguiente ejemplo: [PID 276] Begin 0 End 1 Decoded Task Ho
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
int i, task_begin, task_end;
/* Task notification through rendezvous */
wait_semaphore(sem_task_ready);
task_begin = task­>begin; task_end = task­>end;
signal_semaphore(sem_task_read);
/* Task processing */
for (i = task_begin; i <= task_end; i++) {
if (data­>vector[i] <= 26) {
data­>vector[i] += 96;
}
else {
if (data­>vector[i] <= 52) {
data­>vector[i] += 38;
}
/* Symbol (need to interact with the symbol decoder) */
else {
/* Mutex to guarantee the exclusive use of symbol_decoder */
wait_semaphore(sem_mutex);
symbol­>value = data­>vector[i];
signal_semaphore(sem_symbol_ready);
wait_semaphore(sem_symbol_decoded);
data­>vector[i] = symbol­>value;
signal_semaphore(sem_mutex);
}
}
}
/* Result translated */
printf ("[PID %d] Begin %d End %d Decoded Task ", getpid(), task_begin, task_end);
Página 9 de 10
Escuela Superior de Informática
Universidad de Castilla-La Mancha
Programación Concurrente y de Tiempo Real
Modelo B01 – Semáforos y Memoria Compartida
547
548
549
550
for (i = task_begin; i <= task_end; i++) {
printf("%c", data­>vector[i]); }
printf ("\n");
551
552
553
554
555
}
void notify_task_completed(sem_t * sem_task_processed) {
signal_semaphore(sem_task_processed);
}
symbol_decoder.c
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <definitions.h>
#include <semaphoreI.h>
/* Semaphores and shared memory retrieval */
void get_shm_segments(int *shm_symbol, struct TSymbol_t **p_symbol);
void get_sems(sem_t **p_sem_symbol_ready, sem_t **p_sem_symbol_decoded);
/* Task management */
void get_and_process_task(sem_t *sem_symbol_ready, sem_t *sem_symbol_decoded, struct TSymbol_t *symbol);
 Incluya aquí el código del proceso symbol_decoder (Longitud aprox. ≈ 30 Líneas de código)
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
/******************** Main function ********************/
int main(int argc, char *argv[]) {
struct TSymbol_t *symbol;
int shm_symbol; sem_t *sem_symbol_ready, *sem_symbol_decoded;
/* Get shared memory segments and semaphores */
get_shm_segments(&shm_symbol, &symbol);
get_sems(&sem_symbol_ready, &sem_symbol_decoded);
/* Will work until killed by the manager */
while (TRUE) {
get_and_process_task(sem_symbol_ready, sem_symbol_decoded, symbol);
}
return EXIT_SUCCESS;
}
/******************** Semaphores and shared memory retrieval ********************/
void get_shm_segments(int *shm_symbol, struct TSymbol_t **p_symbol) {
*shm_symbol = shm_open(SHM_SYMBOL, O_RDWR, 0644);
*p_symbol = mmap(NULL, sizeof(struct TSymbol_t), PROT_READ | PROT_WRITE, MAP_SHARED,
*shm_symbol, 0); }
void get_sems(sem_t **p_sem_symbol_ready, sem_t **p_sem_symbol_decoded) {
*p_sem_symbol_ready = get_semaphore(SEM_SYMBOL_READY);
*p_sem_symbol_decoded = get_semaphore(SEM_SYMBOL_DECODED);
}
/******************** Task management ********************/
void get_and_process_task(sem_t *sem_symbol_ready, sem_t *sem_symbol_decoded, struct TSymbol_t *symbol) {
wait_semaphore(sem_symbol_ready);
switch (symbol­>value){
case 53: symbol­>value = 46; break;
case 54: symbol­>value = 44; break;
case 55: symbol­>value = 33; break;
case 56: symbol­>value = 63; break;
case 57: symbol­>value = 95; break; }
signal_semaphore(sem_symbol_decoded);
}
Página 10 de 10