Skip to content

Instantly share code, notes, and snippets.

@nh2
Created December 7, 2020 19:43
Show Gist options
  • Save nh2/8c9fbf8cd9ad1ceba9a160cf50522679 to your computer and use it in GitHub Desktop.
Save nh2/8c9fbf8cd9ad1ceba9a160cf50522679 to your computer and use it in GitHub Desktop.
Demo of how mmap() affects VIRT, RES, SHR memory usage in Linux
// Demo of how mmap() affects VIRT, RES, SHR memory usage in Linux.
//
// A useful resource for more background:
// https://techtalk.intersec.com/2013/07/memory-part-2-understanding-process-memory/
// Required for:
// * `O_TMPFILE`
// * `fallocate()`
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
if (argc != 2) {
fprintf(stderr, "Usage:\n%s MAP_SHARED\n%s MAP_PRIVATE\n", argv[0], argv[0]);
exit(1);
}
int map_flag =
(strcmp(argv[1], "MAP_SHARED") == 0) ? MAP_SHARED :
(strcmp(argv[1], "MAP_PRIVATE") == 0) ? MAP_PRIVATE :
0;
printf("Using %s (numeric value %d)\n", argv[1], map_flag);
// Anonymous unnamed file that does not show in the file system:
//int fd = open("tmpdir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
// To observe file contents in the file system:
int fd = open("tmpdir/mappedfile", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd == -1) {
perror("open tmpdir");
fprintf(stderr, "Please `mkdir tmpdir/` first.\n");
exit(1);
}
const size_t length = 1024 * 1024 * 1024;
if (fallocate(fd, FALLOC_FL_ZERO_RANGE, 0, length) == -1) {
perror("fallocate");
exit(1);
}
// map_flag (see `man 2 mmap`):
// * MAP_SHARED: Changes file contents on disk.
// * MAP_PRIVATE: Does NOT change file contents on disk; uses copy-on-write.
char * region = mmap(NULL, length, PROT_READ | PROT_WRITE, map_flag, fd, 0);
if (region == MAP_FAILED) {
perror("mmap");
exit(1);
}
puts("You should now see 1 GB VIRT in htop. Press Enter to mutate mapped bytes...");
getchar();
// Mutate all bytes in the mmapped region.
for (size_t i = 0; i < length; i++) {
region[i] += 1;
}
// Tell the user what they should expect to see.
if (map_flag == MAP_SHARED) {
puts("Because of MAP_SHARED: You should now see 1 GB VIRT, RES and SHR each in htop.");
// You should now also see tmpdir/mappedfile contents changed,
// unless you used `O_TMPFILE` in which case the file is invisible.
} else if (map_flag == MAP_PRIVATE) {
puts("Because of MAP_PRIVATE: You should now see 1 GB VIRT and RES each in htop. Press Enter to terminate...");
// You should NOT see any change in tmpdir/mappedfile.
} else {
puts("Impossible.");
}
puts("Press Enter to terminate...");
getchar();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment