#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #define PAGE_SIZE 4096 // NOTE: DATA=MAP2=16 seems to trigger in the first few tries // NOTE: 9/9 needs a loop and a few seconds to trigger // NOTE: DATA=9, MAP2=8 does not trigger #define DATA_SIZE 16 #define MAP2_SIZE 16 int shmfd; char shmpath[] = "/dev/shm/mmaptest-XXXXXX"; unsigned char *map1, *map2; unsigned int i; int main(int argc, char *argv[]) { /* create a data file on tmpfs */ shmfd = mkstemp(shmpath); if (shmfd < 0) { perror("mkstemp"); exit(2); } if (unlink(shmpath)) { perror("unlink"); exit(2); } if (ftruncate(shmfd, DATA_SIZE * PAGE_SIZE)) { perror("ftruncate"); exit(2); } /* map a single page from the file */ map1 = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); if (map1 == MAP_FAILED) { perror("mmap 1"); exit(2); } /* remap it to another page in the file */ // NOTE: Does not trigger without remapping // NOTE: Does not trigger for 7, but does trigger for 8 if both sizes are 16 // (DATA_SIZE-2 is sufficiently generic here) if (remap_file_pages(map1, PAGE_SIZE, 0, DATA_SIZE - 2, MAP_SHARED)) { perror("remap_file_pages 1"); exit(2); } /* create a second mapping */ map2 = mmap(NULL, MAP2_SIZE * PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shmfd, 0); if (map2 == MAP_FAILED) { perror("mmap 2"); exit(2); } /* map all of its pages to page 0 */ // NOTE: Remapping only the last page does not trigger for (i = 0; i < MAP2_SIZE; i++) { if (remap_file_pages(map2 + PAGE_SIZE * i, PAGE_SIZE, 0, 0, MAP_SHARED)) { perror("remap_file_pages 3"); exit(2); } } close(shmfd); exit(0); }