/** * mmap_reader.c * * Demonstrates the process for setting up a shared region of memory, then * attempts to read messages from it that are enclosed in 'message' structs. * It's important to note that this is simply a proof of concept; polling the * shared memory every second for a new message is not efficient or safe (in * terms of race conditions, etc). * * If you are on a system with /dev/shm, check this location for the shared * object file once the program has started. * * We also try to be reasonably complete by shutting things down and cleaning up * when the user presses Ctrl+C. * * Compile (Linux): gcc -lrt -Wall -g mmap_reader.c -o reader * Compile (Mac): gcc -Wall -g mmap_reader.c -o reader * Run: ./reader shm_obj_name */ #include #include #include #include #include #include #include #include int g_shm_fd; void *g_block; char *g_shm_name; struct message { unsigned int id; pid_t from_pid; char msg[128]; }; void close_handler(int signo) { printf("Cleaning up shared object\n"); if (munmap(g_block, sizeof(struct message)) == -1) { perror("munmap"); } if (shm_unlink(g_shm_name) == -1) { perror("shm_unlink"); } if (close(g_shm_fd) == -1) { perror("close"); } printf("Goodbye!\n"); exit(0); } int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s shm_obj_name", argv[0]); return 1; } signal(SIGINT, close_handler); signal(SIGTERM, close_handler); g_shm_name = argv[1]; size_t size = sizeof(struct message); int shm_fd = shm_open(g_shm_name, O_CREAT | O_RDWR, S_IRWXU); if (shm_fd == -1) { perror("shm_open"); return 1; } if (ftruncate(shm_fd, size) == -1) { perror("ftruncate"); return 1; } g_block = mmap( NULL, /* Address (we use NULL to let the kernel decide) */ size, /* Size of memory block to allocate */ PROT_READ | PROT_WRITE, /* Memory protection flags */ MAP_SHARED, /* Type of mapping */ shm_fd, /* file descriptor */ 0 /* offset to start at within the file */); if (g_block == MAP_FAILED) { perror("mmap"); } int last_msg = 0; struct message *msg = (struct message *) g_block; while (true) { if (msg->id == last_msg) { sleep(1); continue; } printf("Received message %d from PID %d: '%s'\n", msg->id, msg->from_pid, msg->msg); last_msg = msg->id; } return 0; }