Sometimes it makes sense to double map the same physical memory onto
different locations in address space of process, for example in 64-bit systems have
some parts of your address space to be accessible using 16-bit or 32-bit addresses.
In this example I'll show how to make part of the memory visible through "window"
located at virtual address
0x80000
.
This method isn't as good, as could be just direct manipulation of page tables,
as creation of file mapping of existing memory location effectively clears data in it and also may lead to write into backing store (file), but still could be sometimes useful in low level optmizations.One example of such optimizations - if you have frequently used data in JVM heap, and want to access them quickly, while want to avoid chunked heap, you may double map part of your heap at predefined address, and in fast accessors use low addresses, while in GC code use regular addresses of exactly same data. Not sure, if such approach wouldn't lead to cache coherency problem on CPUs with virtually indexed caches.
If you have ideas how to make double mapping non-overriding, and not using backing storage - please let me know.
#define_GNU_SOURCE 1 #include<stdio.h> #include<unistd.h> #include<sys/mman.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h>char* window = (char*)0x80000;int window_size = 4096;intmake_window(char* where) {char wname[128];char *win1, *win2;int fd; sprintf(wname, "/tmp/__window%x", getpid()); unlink(wname); fd = open(wname, O_CREAT | O_RDWR);if (fd < 0) { perror("open");return 0; }if (ftruncate(fd, (off_t)window_size) < 0) { perror("ftruncate");return 0; } win1 = (char*)mmap(where, window_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);if (win1 == (char*)-1) { perror("mmap1");return 0; } win2 = (char*)mmap((void*)0x80000, window_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);if (win2 == (char*)-1) { perror("mmap2");return 1; }if (close(fd) < 0) { perror("close"); }if (unlink(wname) < 0) { perror("unlink"); }return 1; }intmain() {char *heap;int heap_size = 4096*4096; heap = (char*)mmap(NULL, heap_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);if (heap == (char*)-1) { perror("mmap heap");return 1; } printf("heap at %p\n", heap);if (!make_window(heap+8192)) {return 1; } window[0] = 0x1f; printf("window at %p: in heap=%x in window=%x\n", window, heap[8192], window[0]);return 0; }