#include #include #include #include #include #include #include #include #include #include #define SIZE 19*1024*1024 #define PAGE_SIZE 4096 // 4KB #define CHUNK_SIZE 8 * 1024 // 8KB void compute_md5(const unsigned char *data, size_t length, unsigned char *md5_hash) { MD5_CTX md5_ctx; MD5_Init(&md5_ctx); MD5_Update(&md5_ctx, data, length); MD5_Final(md5_hash, &md5_ctx); } void print_md5(unsigned char *md5_hash) { for (int i = 0; i < MD5_DIGEST_LENGTH; i++) { printf("%02x", md5_hash[i]); } printf("\n"); } unsigned long long tv_to_ms(struct timeval tv) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; } int main() { char c; pid_t pid; int i; int j = 0; struct timeval tv_b, tv_e;; unsigned char md5_hash[MD5_DIGEST_LENGTH]; unsigned long *p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (!p) { perror("fail to get memory"); exit(-1); } printf("0x%lx\n", p); madvise(p, SIZE, MADV_HUGEPAGE); for (j = 0; j < SIZE / 8; j += 8) *(p + j) = j; for (size_t offset = PAGE_SIZE; offset < SIZE; offset += CHUNK_SIZE) { char *str = (char *)p + offset; sprintf(str, "child"); } for (size_t offset = PAGE_SIZE; offset < SIZE; offset += CHUNK_SIZE) { compute_md5((unsigned char *)p + offset, PAGE_SIZE, md5_hash); printf("MD5 of the buffer: "); print_md5(md5_hash); } gettimeofday(&tv_b, NULL); madvise(p, SIZE, MADV_PAGEOUT); gettimeofday(&tv_e, NULL); printf("swp out bandwidth: %ld bytes/ms\n", SIZE/(tv_to_ms(tv_e) - tv_to_ms(tv_b))); pid = fork(); if (pid == 0) { printf("child: freeing some swap\n"); for (size_t offset = 0; offset < SIZE; offset += CHUNK_SIZE) { if (madvise((void *)((char *)p + offset), PAGE_SIZE, MADV_DONTNEED) == -1) { perror("madvise failed"); return -1; } } printf("child: sleep\n"); sleep(5); printf("child: reading swaped data\n"); for (size_t offset = PAGE_SIZE; offset < SIZE; offset += CHUNK_SIZE) { char *str = (char *)p + offset; if (strcmp(str, "child")) printf("%s\n", str); } printf("child: read done\n"); for (size_t offset = PAGE_SIZE; offset < SIZE; offset += CHUNK_SIZE) { compute_md5((unsigned char *)p + offset, PAGE_SIZE, md5_hash); printf("MD5 of the buffer: "); print_md5(md5_hash); } #if 2 } else { printf("parent: sleeping\n"); sleep(1); printf("parent: unmapping origin memory region\n"); munmap(p, SIZE); printf("parent: alloc new memory region\n"); p = mmap(NULL, 9 * 1024 * 1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); for (j = 0; j < 1024 * 1024; j+=8) *(p + j) = j + 10; for (size_t offset = 0; offset < 8 * 1024 * 1024; offset += CHUNK_SIZE) { char *str = (char *)p + offset + PAGE_SIZE; sprintf(str, "parent"); } madvise(p, 9 * 1024 * 1024, MADV_PAGEOUT); #endif } while(1) { sleep(100); } return 0; }