使用/ dev / zero访问大内存(32 GB)

时间:2014-05-06 06:02:09

标签: linux memory mmap

我想使用/dev/zero来存储大量临时数据(32 GB或左右)。我这样做:

fd = open("/dev/zero", O_RDWR );
// <Exit on error>
vbase = (uint64_t*) mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
// <Exit on error>
ftruncate(fd, (off_t) MEMSIZE);

我正在将MEMSIZE从1GB更改为32 GB(执行memtest)以查看是否可以真正访问所有范围。我的内存耗尽1 GB。

我有什么遗失的吗?我正确地映射了吗? 或者我遇到了一些系统限制?我该如何检查是否发生这种情况?

P.S:我运行了很多程序,在一个文件中生成了很多数据,所以我不知道是否有一个人为的上限,只是我似乎遇到了什么。

2 个答案:

答案 0 :(得分:2)

我不得不承认我对你实际上要做的事感到困惑。无论如何,你做什么的几个原因可能不起作用:

  1. 从mmap(2)联机帮助页:“MAP_ANONYMOUS
              映射不受任何文件的支持;其内容初始化为零。忽略fd和offset参数;“
  2. 从null(4)联机帮助页:“写入空或零特殊文件的数据将被丢弃。”
  3. 所以无论如何,在MAP_ANONYMOUS之前,有时会使用mmap'ing / dev / zero来获取匿名(即没有任何文件支持)内存。无需两者兼顾。在任何一种情况下,实际写入所有内存意味着您需要某种后备存储,无论是物理内存还是交换空间。如果你不能保证,mmap()文件系统上的真实文件可能有足够的空间吗?

答案 1 :(得分:0)

了解Linux内核mmap实现:

vm_mmap vm_mmap_pgoff  do_mmap_pgoff  mmap_region  file->f_op->mmap(file, vma) 
  1. 在函数do_mmap_pgoff中,它会检查max_map_count

    if (mm->map_count > sysctl_max_map_count)
        return -ENOMEM;
    
    root> sysctl -a | grep map_count
    vm.max_map_count = 65530
    
  2. 在函数mmap_region中,它检查进程虚拟地址限制(是否无限制)。

    int may_expand_vm(struct mm_struct *mm, unsigned long npages)
    {
                   unsigned long cur = mm->total_vm;          /* pages */
                   unsigned long lim;
    
                   lim = rlimit(RLIMIT_AS) >> PAGE_SHIFT;
    
                   if (cur + npages > lim)
                                  return 0;
                   return 1;
    }
    
    root> ulimit -a | grep virtual
    virtual memory          (kbytes, -v) unlimited
    

    在linux内核中,init任务默认设置为rlimit

    [RLIMIT_AS]                      = {  RLIM_INFINITY,  RLIM_INFINITY },     \
    
    #ifndef RLIM_INFINITY
    # define RLIM_INFINITY                (~0UL)
    #endif
    

    为了证明这一点,请使用test_mem程序

    tmp> ./test_mem 
    RLIMIT_AS limit got sucessfully:
    soft_limit=4294967295, hard_limit=4294967295
    RLIMIT_DATA limit got sucessfully:
    soft_limit=4294967295, hard_limit=4294967295
    
    struct rlimit rl;
    int ret;
    ret = getrlimit(RLIMIT_AS, &rl);
    if (ret == 0) {
        printf("RLIMIT_AS limit got sucessfully:\n");
        printf("soft_limit=%lld, hard_limit=%lld\n", (long long)rl.rlim_cur,          (long long)rl.rlim_max);
    }
    

    这意味着64位操作系统中32位应用的无限意味着0xFFFFFFFF。更改shell虚拟地址限制,它可以正确反映。

    root> ulimit -v 1024000
    tmp> ./test_mem 
    RLIMIT_AS limit got sucessfully:
    soft_limit=1048576000, hard_limit=1048576000
    RLIMIT_DATA limit got sucessfully:
    soft_limit=4294967295, hard_limit=4294967295
    
  3. mmap_region中,有一项问责检查

    accountable_mapping   security_vm_enough_memory_mm  cap_vm_enough_memory  __vm_enough_memory  overcommit/swap/admin and user reserve handling.
    
  4. 请按照以下三个步骤检查是否可以见面。