0

Hello I am trying to back up a vector by mmap. However, I have tried msync then munmap but it doesn't work. After I write to the (char *) then munmap the file, the file has no content. The mmap file is also created with flag MAP_SHARED. Would really appreciate it if anyone can help.

    //update file descriptor
    if ((fd = open(filename.c_str(), O_RDWR | S_IRWXU)) < 0) { //| O_CREAT
        printf("ERROR opening file %s for writing", filename.c_str());
        exit(1);
    }


    //lseek create a file large enough
    off_t i = lseek(fd, frontier_size * URL_MAX_SIZE, SEEK_SET);
    if (i != frontier_size * URL_MAX_SIZE) {
        cout << "failed to seek";
    }

    //reposition and write 3 bytes to the file else will failed to read
    char buff[3] = "ta";

    ssize_t kk = lseek(fd, 0, SEEK_SET);
    if (kk < 0) {
        cout << "failed to reposition";
    }

    ssize_t temp_write = write(fd, (void *)& buff, 2);
    if (temp_write < 0) {
        cout << "failed to write";
        cout << temp_write;
    }


    //reposition to begining
    ssize_t k = lseek(fd, 0, SEEK_SET);
    if (k < 0) {
        cout << "failed to reposition";
    }



    char * map = (char *)mmap(0, frontier_size * URL_MAX_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);


    if (map == MAP_FAILED) {
        printf("failed mmap");
        exit(1);
    }
mmap_frontier = map;
    //write to frontier
    for (int i = 0; i < frontier.size(); ++i) {
        strcpy(mmap_frontier, frontier[i].c_str());
        mmap_frontier += URL_MAX_SIZE;

    }

    mmap_frontier -= frontier.size() * URL_MAX_SIZE;


    ssize_t k = lseek(fd, 0, SEEK_SET);
    if (k < 0) {
        cout << "failed to reposition";
    }

    int sync = msync((void *)0, frontier.size() * URL_MAX_SIZE, MS_ASYNC);
    if (sync < 0 ) {
        cout << "failed to sync";
    }

    int unmap = munmap((void *)0, frontier.size() * URL_MAX_SIZE);
    if (unmap < 0) {
        cout << "failed to unmap";
    }
Erin
  • 83
  • 1
  • 9

1 Answers1

0

There are quite a few problems with your code, and with the question:

  • S_IRWXU is the 3rd argument to open(), not a flag for the 2nd parameter.
  • mmap() won't work correctly if the file is too small. You can use ftruncte() to set the file size correctly. You tried to seek past the total size of the mapping and write a couple of bytes ("ta"), but before doing that you issued the seek lseek(fd, 0, SEEK_SET) which means the file size was set to 3 rather than mapping_size+3.
  • You're not backing the vector with an mmapped file, the vector has nothing to do with it, the vector uses its own memory that isn't related in any way to this mapping (please edit your question...).
  • You called msync() with the address (void *)0, so the actual address which needs to be synced, map, is not being synced.
  • Likewise, you called munmap() with the address (void *)0, so the actual address which needs to be unmapped is not being unmapped.
  • You called msync() with MS_ASYNC, which means there's no guarantee that the sync happens before you read the file's contents.

Here's what's working for me (error handling omitted for brevity):

unsigned frontier_size = 2;
const unsigned URL_MAX_SIZE = 100;

int fd = open("data", O_RDWR);
loff_t size = frontier_size * URL_MAX_SIZE;
ftruncate(fd, size);
char *map = (char *)mmap(0, size, PROT_WRITE, MAP_SHARED, fd, 0);
strcpy(map, "hello there");
msync(map, size, MS_SYNC);
munmap(map, size);
close(fd);
root
  • 5,528
  • 1
  • 7
  • 15