mmap:无法分配内存

前端之家收集整理的这篇文章主要介绍了mmap:无法分配内存前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个C程序,用C计算页面错误服务时间.
对于这个程序,我有2个大文件(每个小于3GB – 几乎与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,POSIX_FADV_RANDOM);
    posix_fadvise(fd2,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,fd2,0);
    if (addr2 == MAP_Failed){
        handle_error("mmap");
    }

    madvise(addr1,MADV_RANDOM);
    madvise(addr2,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,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,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的数据,每次访问对应文件的数据都会导致页面错误.我们在循环中的映射区域上执行10个随机读数,并测量此操作所需的平均时间.

解决方法

看看你得到的编译器警告.你在这里有一个整数溢出:#define SIZE_OF_MEMORY 2 * GB.等于2 ^ 31 == 0b1000 … 0,对于signed int等于INT_MIN.这就是mmap失败的原因.

您应该在定义中使用unsigned literals

#define KB (1024u)
#define MB (1024u * KB)
#define GB (1024u * MB)
#define SIZE_OF_MEMORY (2u * GB)

猜你在找的C&C++相关文章