Mmap: memory cannot be allocated

I have a C program that calculates the page maintenance time in C. For this program I have 2 large files (less than 3 GB each - almost the size of RAM)

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include "rdstc.h" #include "config.h" #define KB 1024 #define MB 1024 * KB #define GB 1024 * MB #define SIZE_OF_MEMORY 1 * GB // Main memory size #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]){ int fd1, fd2; char *addr1, *addr2, c; int i, j; long long unsigned int s_t, e_t, t=0; if (argc != 3){ printf("usage: a.out <file1> <file2> \n"); exit(EXIT_FAILURE); } if ((fd1 = open(argv[1], O_RDONLY)) == -1){ handle_error("open"); } if ((fd2 = open(argv[2], O_RDONLY)) == -1){ handle_error("open"); } posix_fadvise(fd1, 0, 0, POSIX_FADV_RANDOM); posix_fadvise(fd2, 0, 0, POSIX_FADV_RANDOM); addr1 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd1, 0); if (addr1 == MAP_FAILED){ handle_error("mmap"); } addr2 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd2, 0); if (addr2 == MAP_FAILED){ handle_error("mmap"); } madvise(addr1, 0, MADV_RANDOM); madvise(addr2, 0, MADV_RANDOM); j = 32; // default read ahead size if 256 blocks (assuming each block is of 512 bytes) for(i = 0; i < ITERATIONS; i++){ s_t = rdtsc(); c = addr1[i + j*4*KB]; // read at multiple of page size, so every read causes a page fault j *= 2; e_t = rdtsc(); t += (e_t - s_t); } printf("Time required to service a page faut is %f \n", (t/ITERATIONS)/CPU_FREQ); munmap(addr1, SIZE_OF_MEMORY); munmap(addr2, SIZE_OF_MEMORY); return 0; } 

I get the following compiler warnings:

 lmelvix@Melvix :~/projects/mem$ gcc mem1_4.c -lm mem1_4.c: In function 'main': mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro 'MB' #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro 'GB' #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:40:30: note: in expansion of macro 'SIZE_OF_MEMORY' addr1 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd1, 0); ^ mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro 'MB' #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro 'GB' #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:44:30: note: in expansion of macro 'SIZE_OF_MEMORY' addr2 = (char *) mmap(0, SIZE_OF_MEMORY, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd2, 0); ^ mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro 'MB' #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro 'GB' #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:62:19: note: in expansion of macro 'SIZE_OF_MEMORY' munmap(addr1, SIZE_OF_MEMORY); ^ mem1_4.c:11:17: warning: integer overflow in expression [-Woverflow] #define MB 1024 * KB ^ mem1_4.c:12:19: note: in expansion of macro 'MB' #define GB 1024 * MB ^ mem1_4.c:13:28: note: in expansion of macro 'GB' #define SIZE_OF_MEMORY 2 * GB // Main memory size ^ mem1_4.c:63:19: note: in expansion of macro 'SIZE_OF_MEMORY' munmap(addr2, SIZE_OF_MEMORY); ^ 

When I run it with a command, I get an error

 ./a.out file1.txt file2.txt mmap: Cannot allocate memory 

What does the code do? We match both files using flags

MAP_PRIVATE (so that no other process accesses this file) and MAP_POPULATE (so

when we call that the mmap () file is displayed in memory), as well as the PROT_READ security flag.

First, we map file1, and since we use MAP_POPULATE, the full RAM is populated with data corresponding to this file. After that, we map file2 using the same flags, and now we have file2, which is fully displayed in RAM. Thus, access to the data of file1 will cause page errors, since file2 occupies all available RAM. We also call madvise () syscall with the MADV_RANDOM flag set to tell the kernel not to read page reads ahead, for both files. So, now, as soon as this initial setup is done with file 2, which occupies all available RAM, we randomly get the data corresponding to file 1 (to avoid any effect of future read optimization performed by the kernel, as well as to avoid reading from L3 cache) . Since the RAM is populated with data corresponding to file2, each access to the data corresponding to the file will cause the page to crash. We perform 10 random reads in the displayed area in a loop and measure the average time required for this operation.

+7
c memory-management linux memory operating-system
source share
1 answer

take a look at the compiler warning you get. Here you have a solid overflow: #define SIZE_OF_MEMORY 2 * GB . This is 2^31 == 0b1000 ... 0 , which for a signed int is INT_MIN. This is why mmap fails.

You must use unsigned literals in your definitions:

 #define KB (1024u) #define MB (1024u * KB) #define GB (1024u * MB) #define SIZE_OF_MEMORY (2u * GB) 
+6
source share

All Articles