Hello everyone, I am the Information Guy~Today, I will share a core system call in Linux: mmap (Memory Mapping),
It allows for the direct mapping of files or devices into a process’s virtual address space. Through mmap, three powerful functionalities can be achieved:
- File access is transformed into memory read/write operations
- The kernel automatically handles data loading/synchronization
- Supports the creation of pure memory mappings (independent of files)
1. Why do we need mmap?
First and foremost, it is for performance; by using mmap, we can reduce data copying. Traditionally, we use read/write which requires kernel-user space data copying.
Is mmap always faster than read/write?
Actually, for small files or single read/write operations less than 4KB, the overhead of system calls may be higher. The advantage of mmap is evident in scenarios involving frequent access to large files.
At the same time, it simplifies programming by transforming file operations into pointer access (for example: <span>int *data = (int*)mapped_addr;</span>).Interestingly, it also enables efficient IPC, allowing for easy inter-process shared memory communication. However, for multi-process writing, it is still necessary to use inter-process synchronization mechanisms (such as file-based locks<span>flock()</span> or mutexes in shared memory). Additionally, when handling large files, only the accessed portions are loaded into memory, theoretically reaching TB levels, limited by virtual address space. For allocations greater than 128KB, it can replace malloc for large memory allocations.
2. Core Working Principles

- Page Table Mapping: Establishing the mapping relationship between virtual addresses and physical memory/files
- On-Demand Loading: Accessing unloaded areas triggers a page fault
- Write-Back Strategy:
<span>MAP_SHARED</span>: Modifications are synchronized to the underlying file<span>MAP_PRIVATE</span>: Copy-on-Write
3. Detailed Explanation of Core APIs
1. Creating a Mapping
#include <sys/mman.h>
void *mmap(void *addr, // Suggested address (usually NULL)
size_t length, // Length of mapping (multiple of page size)
int prot, // Protection permissions
int flags, // Mapping type flags
int fd, // File descriptor
off_t offset); // File offset
Key Parameter Combinations:
| Mapping Type | Flags Combination | fd Value | Usage |
|---|---|---|---|
| File Shared Mapping | MAP_SHARED | ≥0 | Inter-process IPC |
| File Private Mapping | MAP_PRIVATE | ≥0 | Read-only/Copy-on-Write file |
| Anonymous Shared Mapping | MAP_SHARED | MAP_ANONYMOUS | -1 | Shared memory between parent and child processes |
| Anonymous Private Mapping | MAP_PRIVATE | MAP_ANONYMOUS | -1 | Large memory allocation |
prot Flags:
- PROT_READ: Readable
- PROT_WRITE: Writable
- PROT_EXEC: Executable
- PROT_NONE: No access
2. Unmapping
int munmap(void *addr, size_t length); // Returns 0 on success, -1 on failure
3. Synchronizing Data (Optional)
int msync(void *addr, size_t len, int flags);
// flags: MS_ASYNC (asynchronous), MS_SYNC (synchronous), MS_INVALIDATE (invalidate cache)
4. Some Examples
Example 1: Anonymous Memory Allocation (Replacing malloc)
// Allocate 1GB of private memory
size_t size = 1 << 30; // 1GB
void *mem = mmap(NULL, size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
if(mem == MAP_FAILED) {
perror("mmap failed");
exit(1);
}
// Use memory (automatically initialized to 0)
int *array = (int*)mem;
array[0] = 42;
// Release
munmap(mem, size);
Example 2: File Shared Mapping (Inter-process IPC)
// Process A: Create and write to a shared file
int fd = open("shared_data.bin", O_RDWR | O_CREAT, 0666);
ftruncate(fd, 4096); // Extend file size
void *ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
sprintf((char*)ptr, "Hello from Process A");
// Process B: Read the same file
void *ptr2 = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);
printf("Received: %s\n", (char*)ptr2); // Output message from Process A
// Cleanup
munmap(ptr, 4096);
close(fd);
5. Points to Note
-
Alignment Requirements:
<span>offset</span>must be a multiple of the system page size- Page size can be obtained using
<span>sysconf(_SC_PAGESIZE)</span>
File Extension Pitfalls:
// Error: Shrinking the file after mapping will cause SIGBUS
ftruncate(fd, 100);
// Correct: Ensure the file is large enough before mapping
ftruncate(fd, file_size);
void *mem = mmap(..., fd, ...);
Shared Memory Synchronization:
- Multi-process/thread access requires additional synchronization mechanisms (such as mutexes)
- Call
<span>msync()</span><span> after writing to ensure data persistence</span>
Finally
I have collected some embedded learning materials, reply with 【1024】 in the public account to find the download link!
Recommended Articles: Click the blue text to jump
☞ Collection | Comprehensive Guide to Linux Application Programming
☞ Collection | Learn Some Networking Knowledge
☞ Collection | Handwritten C Language
☞ Collection | Handwritten C++ Language
☞ Collection | Experience Sharing
☞ Collection | From Microcontrollers to Linux
☞ Collection | Power Control Technology
☞ Collection | Essential Mathematics for Embedded Systems
☞ Collection | MCU Advanced Collection