linux-sysprog · advanced · ~15 min

POSIX Memory Mapped Ring Monitor

Structure and coordinate shared memory communication channels safely in C.

Challenge

Shared memory mapped files (mmap, shm_open) share state across process boundaries. Coordinated concurrent access uses memory fences and lockless atomic status flags.

Your Task

Given the memory-mapped status layout:

typedef struct {
    uint32_t magic;         // 0x53484D31 ("SHM1")
    uint32_t write_sequence;
    uint32_t message_count;
    char last_message[64];
} ShmHeader;

Implement:

int shm_format_region(void *region, size_t size);
int shm_publish_message(void *region, size_t size, const char *msg);
int shm_read_latest(const void *region, size_t size, char *out_buf, size_t out_cap, uint32_t *out_seq);

Rules

  1. shm_format_region: if region == NULL or size < sizeof(ShmHeader), return -1. Zero the struct, set magic = 0x53484D31, write_sequence = 0, message_count = 0, and return 0.
  2. shm_publish_message: if region == NULL, msg == NULL, size < sizeof(ShmHeader), or magic != 0x53484D31, return -1. Increment write_sequence, increment message_count, copy msg into last_message (truncating at 63 chars with NUL), and return 0.
  3. shm_read_latest: if region == NULL, out_buf == NULL, out_seq == NULL, size < sizeof(ShmHeader), or magic != 0x53484D31, return -1. If message_count == 0, return 1 (no messages yet). Otherwise, copy last_message to out_buf (up to out_cap), write write_sequence to *out_seq, and return 0.

Example

char mem[sizeof(ShmHeader)];
shm_format_region(mem, sizeof(mem));
shm_publish_message(mem, sizeof(mem), "heartbeat");
char buf[64]; uint32_t seq;
shm_read_latest(mem, sizeof(mem), buf, sizeof(buf), &seq); // returns 0, seq == 1

Input format

region: pointer to shared memory buffer; size: buffer capacity.

Output format

Returns 0 on success, 1 on empty, -1 on invalid format/arguments.

Constraints

Zero dynamic allocations. Bounded string copies.

Starter code

#include <stddef.h>
#include <stdint.h>

typedef struct {
    uint32_t magic;
    uint32_t write_sequence;
    uint32_t message_count;
    char last_message[64];
} ShmHeader;

int shm_format_region(void *region, size_t size) {
    (void)region; (void)size;
    return -1;
}
int shm_publish_message(void *region, size_t size, const char *msg) {
    (void)region; (void)size; (void)msg;
    return -1;
}
int shm_read_latest(const void *region, size_t size, char *out_buf, size_t out_cap, uint32_t *out_seq) {
    (void)region; (void)size; (void)out_buf; (void)out_cap; (void)out_seq;
    return -1;
}

Common mistakes

Forgetting to check magic marker; buffer overflow on last_message copy.

Edge cases to handle

Unformatted region (bad magic) rejected; reading from formatted region with 0 messages returns 1.

Background lessons

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.