Implementation and Usage Guide for Memory Mapped File I/O in C

Core Advantages of Memory Mapped I/O

  • Higher performance than standard read/write operations by reducing redundant data copies between kernel space and user space
  • Intuitive file access via regular memory pointer operations, eliminating the need for custom buffer management logic
  • Native support for inter-process data sharing when multiple processes map the same underlying file
  • Efficient handling of large files, as data is loaded into physical memory only when accessed, rather than loading the entire file upfront

Standard Implementation Workflow

  1. Open the target file with appropriate read/write permissions using the open() system call
  2. Retrieve the current file size by moving the file offset to the end of the file with lseek()
  3. Resize the file to a 4KB aligned size (4096 bytes in this example) using ftruncate() to ensure it can hold the mapped data
  4. Map the file to the process virtual address space with mmap(), specifying access permissions and sharing behavoir
  5. Close the file descriptor once the mapping is created, as it is no longer required for accessing the mapped content
  6. Write or read data directly to/from the mapped memory region using standard memory operations
  7. Synchronize in-memory changes to the underlying file on disk with msync() to prevent data loss
  8. Verify the written content by reading directly from the mapped memory address
  9. Release the mapped memory region with munmap() when operations are complete to free system resources

Sample Implementation Code

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

int main() {
    // Open target file with read/write permissions, create if it does not exist
    int file_handle = open("mapped_io_test.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    if (file_handle == -1) {
        perror("File open failed");
        exit(EXIT_FAILURE);
    }

    // Calculate current file size
    off_t current_file_sz = lseek(file_handle, 0, SEEK_END);
    const size_t map_region_sz = 4096;

    // Resize file to match mapping region size
    if (ftruncate(file_handle, map_region_sz) == -1) {
        perror("File resize failed");
        close(file_handle);
        exit(EXIT_FAILURE);
    }

    // Create shared read/write mapping of the file
    void *map_base = mmap(NULL, map_region_sz, PROT_READ | PROT_WRITE, MAP_SHARED, file_handle, 0);
    if (map_base == MAP_FAILED) {
        perror("Memory mapping creation failed");
        close(file_handle);
        exit(EXIT_FAILURE);
    }

    // File descriptor can be closed after successful mapping
    close(file_handle);

    // Write test data to mapped memory region
    const char *test_content = "Greetings from Memory Mapped I/O!";
    strncpy((char *)map_base, test_content, strlen(test_content) + 1);

    // Synchronize changes to persistent storage
    if (msync(map_base, map_region_sz, MS_SYNC) == -1) {
        perror("Data sync to disk failed");
        munmap(map_base, map_region_sz);
        exit(EXIT_FAILURE);
    }

    // Print content stored in mapped region
    printf("Mapped file content: %s\n", (char *)map_base);

    // Clean up mapped memory region
    if (munmap(map_base, map_region_sz) == -1) {
        perror("Memory mapping release failed");
        exit(EXIT_FAILURE);
    }

    return EXIT_SUCCESS;
}

Expected Output

Mapped file content: Greetings from Memory Mapped I/O!

Tags: c programming System Programming Memory Management File I/O

Posted on Sat, 09 May 2026 02:08:11 +0000 by jwmessiah