c - 映射: Cannot allocate memory

标签 c linux memory memory-management operating-system

我有一个 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, 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 次随机读数,并测量此操作所需的平均时间。

最佳答案

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

您应该使用 unsigned literals在你的定义中:

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

关于c - 映射: Cannot allocate memory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35543952/

相关文章:

c - 一组点的最大周长边界矩形

linux - 通过 ssh 调用日期时区不匹配

c - readlink 系统调用有什么作用?

c - 在编译时有一个结构体

c - 用 C 语言实现多线程按键事件

java - 资源使用过多 : memcached Linux Centos 7

c++ - 为数据库实现 block 存储

c++ - 在 map::at() 中内存字符串表示差异抛出错误

c - 为什么 fscanf() 不工作?

java - 在树莓派中编译安卓应用