Skip to content

Instantly share code, notes, and snippets.

@marcetcheverry
Created May 25, 2011 14:05
Show Gist options
  • Select an option

  • Save marcetcheverry/991042 to your computer and use it in GitHub Desktop.

Select an option

Save marcetcheverry/991042 to your computer and use it in GitHub Desktop.

Revisions

  1. Marc revised this gist May 25, 2011. 1 changed file with 62 additions and 0 deletions.
    62 changes: 62 additions & 0 deletions mapread.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,62 @@
    #include <stdlib.h>
    #include <stdio.h>
    #include <stdint.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    #include <unistd.h>

    int main(int argc, const char *argv[])
    {
    const char *filepath = "/tmp/mmapped.bin";

    int fd = open(filepath, O_RDONLY, (mode_t)0600);

    if (fd == -1)
    {
    perror("Error opening file for writing");
    exit(EXIT_FAILURE);
    }

    struct stat fileInfo = {0};

    if (fstat(fd, &fileInfo) == -1)
    {
    perror("Error getting the file size");
    exit(EXIT_FAILURE);
    }

    if (fileInfo.st_size == 0)
    {
    fprintf(stderr, "Error: File is empty, nothing to do\n");
    exit(EXIT_FAILURE);
    }

    printf("File size is %ji\n", (intmax_t)fileInfo.st_size);

    char *map = mmap(0, fileInfo.st_size, PROT_READ, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
    {
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
    }

    for (off_t i = 0; i < fileInfo.st_size; i++)
    {
    printf("Found character %c at %ji\n", map[i], (intmax_t)i);
    }

    // Don't forget to free the mmapped memory
    if (munmap(map, fileInfo.st_size) == -1)
    {
    close(fd);
    perror("Error un-mmapping the file");
    exit(EXIT_FAILURE);
    }

    // Un-mmaping doesn't close the file, so we still need to do that.
    close(fd);

    return 0;
    }
  2. Marc created this gist May 25, 2011.
    101 changes: 101 additions & 0 deletions mapwrite.c
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,101 @@
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <string.h>

    int main(int argc, const char *argv[])
    {
    if (argc < 2)
    {
    fprintf(stderr, "Need at least one argument to write to the file\n");
    exit(EXIT_FAILURE);
    }

    const char *text = argv[1];
    printf("Will write text '%s'\n", text);

    /* Open a file for writing.
    * - Creating the file if it doesn't exist.
    * - Truncating it to 0 size if it already exists. (not really needed)
    *
    * Note: "O_WRONLY" mode is not sufficient when mmaping.
    */

    const char *filepath = "/tmp/mmapped.bin";

    int fd = open(filepath, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);

    if (fd == -1)
    {
    perror("Error opening file for writing");
    exit(EXIT_FAILURE);
    }

    // Stretch the file size to the size of the (mmapped) array of char

    size_t textsize = strlen(text) + 1; // + \0 null character

    if (lseek(fd, textsize-1, SEEK_SET) == -1)
    {
    close(fd);
    perror("Error calling lseek() to 'stretch' the file");
    exit(EXIT_FAILURE);
    }

    /* Something needs to be written at the end of the file to
    * have the file actually have the new size.
    * Just writing an empty string at the current file position will do.
    *
    * Note:
    * - The current position in the file is at the end of the stretched
    * file due to the call to lseek().
    * - An empty string is actually a single '\0' character, so a zero-byte
    * will be written at the last byte of the file.
    */

    if (write(fd, "", 1) == -1)
    {
    close(fd);
    perror("Error writing last byte of the file");
    exit(EXIT_FAILURE);
    }


    // Now the file is ready to be mmapped.
    char *map = mmap(0, textsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
    {
    close(fd);
    perror("Error mmapping the file");
    exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < textsize; i++)
    {
    printf("Writing character %c at %zu\n", text[i], i);
    map[i] = text[i];
    }

    // Write it now to disk
    if (msync(map, textsize, MS_SYNC) == -1)
    {
    perror("Could not sync the file to disk");
    }

    // Don't forget to free the mmapped memory
    if (munmap(map, textsize) == -1)
    {
    close(fd);
    perror("Error un-mmapping the file");
    exit(EXIT_FAILURE);
    }

    // Un-mmaping doesn't close the file, so we still need to do that.
    close(fd);

    return 0;
    }