mmap_reader.c
/**
* 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 <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
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;
}