1/**
2 * Shared Memory Consumer
3 *
4 * Reads data from POSIX shared memory written by shm_producer.
5 * Run shm_producer first, then this program.
6 *
7 * Build: make
8 * Usage: ./shm_consumer
9 *
10 * Note: Link with -lrt -lpthread on Linux
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <fcntl.h>
16#include <sys/mman.h>
17#include <unistd.h>
18#include <semaphore.h>
19
20#define SHM_NAME "/study_shm"
21#define SEM_READY "/study_sem_ready"
22#define SEM_DONE "/study_sem_done"
23
24#define NUM_ITEMS 10
25
26typedef struct {
27 int id;
28 double value;
29 char label[64];
30} item_t;
31
32typedef struct {
33 int count;
34 item_t items[NUM_ITEMS];
35} shared_data_t;
36
37int main(void) {
38 /* Open semaphores */
39 sem_t *sem_ready = sem_open(SEM_READY, 0);
40 sem_t *sem_done = sem_open(SEM_DONE, 0);
41
42 if (sem_ready == SEM_FAILED || sem_done == SEM_FAILED) {
43 fprintf(stderr, "Run shm_producer first!\n");
44 exit(EXIT_FAILURE);
45 }
46
47 /* Wait for data to be ready */
48 printf("Consumer: waiting for producer...\n");
49 sem_wait(sem_ready);
50
51 /* Open shared memory */
52 int shm_fd = shm_open(SHM_NAME, O_RDONLY, 0666);
53 if (shm_fd < 0) {
54 perror("shm_open");
55 exit(EXIT_FAILURE);
56 }
57
58 shared_data_t *shm = mmap(NULL, sizeof(shared_data_t),
59 PROT_READ, MAP_SHARED, shm_fd, 0);
60 if (shm == MAP_FAILED) {
61 perror("mmap");
62 exit(EXIT_FAILURE);
63 }
64
65 /* Read and display data */
66 printf("Consumer: reading %d items from shared memory\n", shm->count);
67
68 double total = 0.0;
69 for (int i = 0; i < shm->count && i < NUM_ITEMS; i++) {
70 printf(" [%d] %s = %.2f\n",
71 shm->items[i].id, shm->items[i].label,
72 shm->items[i].value);
73 total += shm->items[i].value;
74 }
75 printf(" Total: %.2f, Average: %.2f\n",
76 total, total / shm->count);
77
78 /* Signal producer that we're done */
79 sem_post(sem_done);
80
81 /* Cleanup */
82 sem_close(sem_ready);
83 sem_close(sem_done);
84 sem_unlink(SEM_READY);
85 sem_unlink(SEM_DONE);
86 munmap(shm, sizeof(shared_data_t));
87 close(shm_fd);
88 shm_unlink(SHM_NAME);
89
90 printf("Consumer: done, resources cleaned up\n");
91 return 0;
92}