Search code examples
clinuxmmap

Writing and reading structs from file using mmap


I am trying to read and write a struct using mmap, however the changes I do after the mmap are not being persisted to the disk or are not being loaded correctly.

Here's my code sample, when run the first time the file is created and the prints show the correct data, on the second time when the file already exists the struct is empty, filled with 0's. So it looks like the changes were not written to the file but I am having trouble figuring out why.

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>


typedef struct {
    int age;
    char name[128];
} person;

int main(int argc, char *argv[argc]){
    char filename [] = "data.person";
    int fd = open(filename, O_RDWR | O_CREAT , S_IRWXU);
    if (fd == -1) {
        printf("Failed to create version vector file, error is '%s'", strerror(errno));
    exit(1);
    }
    struct stat st;
    fstat(fd, &st);
    person *p;
    if (st.st_size ==  0) {
        ftruncate(fd, sizeof(person));
    p = (person *) mmap(0, sizeof(person), PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
    strcpy(p[0].name, "Hello");
    p[0].age = 10;
        msync(p, sizeof(person), MS_SYNC);
    }else{
    p = (person *) mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if( p == MAP_FAILED){
        printf("mmap failed with error '%s'\n", strerror(errno));
        exit(0);
    }
    }
    printf("%s %d\n", p->name, p->age);
    munmap(p, sizeof(person));
    close(fd);
}

My OS is manjaro 20 and the gcc version is 10.1


Solution

  • Do not use MAP_PRIVATE because:

              Create a private copy-on-write mapping.  Updates to the
              mapping are not visible to other processes mapping the same
              file, and are not carried through to the underlying file.  It
              is unspecified whether changes made to the file after the
              mmap() call are visible in the mapped region.