我有一个用C语言编写的程序,可以计算页面错误服务时间。对于这个程序,我有两个大文件(每个文件都小于3GB - 几乎是RAM大小)。
我收到了以下编译器警告:
当我使用该命令运行时,我遇到了错误。
代码是做什么的? 我们使用标志将两个文件映射起来。使用MAP_PRIVATE(使其他进程无法访问此文件)和MAP_POPULATE(使调用mmap()时完整的文件映射到内存中)以及PROT_READ保护标志。首先,我们映射file1,并且由于我们使用MAP_POPULATE,因此对应于此文件的数据填充了完整的RAM。然后我们使用相同的标志映射file2,因此现在我们已经完全将file2映射到RAM中。因此,访问file1的数据将导致页面故障,因为file2占用了所有可用的RAM。我们还使用MADV_RANDOM标志调用madvise()系统调用,以建议内核不要进行预读取页面的读取,对于两个文件都是如此。因此,现在一旦使用file2占据了所有可用的RAM来完成这些初始设置之后,我们就会随机访问file1的数据(以避免内核执行的预读取优化的任何影响,并避免从L3缓存中读取)。由于RAM填充了与file2对应的数据,因此对file对应的数据的每次访问将导致页面故障。我们在循环中对映射区域执行10次随机读取并测量所需的平均时间。
#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;
}
我收到了以下编译器警告:
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);
^
当我使用该命令运行时,我遇到了错误。
./a.out file1.txt file2.txt
mmap: Cannot allocate memory
代码是做什么的? 我们使用标志将两个文件映射起来。使用MAP_PRIVATE(使其他进程无法访问此文件)和MAP_POPULATE(使调用mmap()时完整的文件映射到内存中)以及PROT_READ保护标志。首先,我们映射file1,并且由于我们使用MAP_POPULATE,因此对应于此文件的数据填充了完整的RAM。然后我们使用相同的标志映射file2,因此现在我们已经完全将file2映射到RAM中。因此,访问file1的数据将导致页面故障,因为file2占用了所有可用的RAM。我们还使用MADV_RANDOM标志调用madvise()系统调用,以建议内核不要进行预读取页面的读取,对于两个文件都是如此。因此,现在一旦使用file2占据了所有可用的RAM来完成这些初始设置之后,我们就会随机访问file1的数据(以避免内核执行的预读取优化的任何影响,并避免从L3缓存中读取)。由于RAM填充了与file2对应的数据,因此对file对应的数据的每次访问将导致页面故障。我们在循环中对映射区域执行10次随机读取并测量所需的平均时间。