Search code examples
cposixshared-memory

How to use struct in POSIX shared memory?


I want my POSIX shared memory segment to conform to a particular structure. I think this code creates the shared memory segment in the shape of the struct.

(File creating the shared memory segment)

typedef struct {
  int cnt;
  char buf[segsize];
} shmseg_t;

int shm_fd = shm_open(shm_name, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, sizeof(shmseg_t);
void* addr = mmap(NULL, sizeof(shmseg_t), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

How do I write data from a file to the different fields of the struct in the shared memory?

(File writing to the shared memory segment)

int shm_fd = shm_open(shm_name, O_WRONLY, 0);
ftruncate(shm_fd, segsize);
void* addr = mmap(NULL, segsize, PROT_WRITE, MAP_SHARED, shm_fd, 0);
// How do I get shmp, which should be a shmseg_t struct?
shmp->cnt = read(fd, shmp->buf, segsize);

And how do I get out the data that was written to the struct in the shared memory?

(File reading from the shared memory segment)

int shm_fd = shm_open(shm_name, O_RDONLY, 0);
ftruncate(shm_fd, segsize);
void* addr = mmap(NULL, segsize, PROT_READ, MAP_SHARED, shm_fd, 0);
// How to get out shmp->cnt and shmp->buf?

Solution

  • It is unclear whether you want to share the entire structure or just buf.

    Option 1: Make buf a pointer, and share what it points to.

    typedef struct {
      int cnt;
      char *buf;
    } shmseg_t;
    
    ftruncate(shm_fd, segsize);
    void* addr = mmap(NULL, segsize,
                      PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    assert(addr != MAP_FAILED);
    
    shm_seg_t shmp = {
        .cnt = ???,  // Whatever value of cnt you want.
        .buf = addr,
    };
    

    Option 2: Share the entire struct.

    typedef struct {
      int cnt;
      char buf[segsize];
    } shmseg_t;
    
    ftruncate(shm_fd, sizeof(shmseg_t));
    void* addr = mmap(NULL, sizeof(shmseg_t),
                      PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    assert(addr != MAP_FAILED);
    
    shm_seg_t *shmp = addr;
    

    If you share it this way, reading and writing are not really different (but you do need to use memory barriers or synchronization).