Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/206.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
android mmap因内存不足而失败_Android_Memory_Android Ndk_Mmap - Fatal编程技术网

android mmap因内存不足而失败

android mmap因内存不足而失败,android,memory,android-ndk,mmap,Android,Memory,Android Ndk,Mmap,我到处寻找答案,但我想我已经找到了极限。我的问题似乎与此有关:但没有提供答案 我的问题是,我试图通过mmap调用从文件中映射457232384字节的内存。在安卓5.1.1的两个不同设备(三星Galaxy Note 3和OnePlus一个,每个3GB内存)上,该调用失败,错误为12“内存不足”。实际上,当我试图分配超过300MB的内存时,调用失败。313524224字节(299MB)有效,314572800字节(300MB)无效 问题是,同样的呼叫在第三台设备上工作,而第三台设备仍在安卓4.4.2

我到处寻找答案,但我想我已经找到了极限。我的问题似乎与此有关:但没有提供答案

我的问题是,我试图通过mmap调用从文件中映射457232384字节的内存。在安卓5.1.1的两个不同设备(三星Galaxy Note 3和OnePlus一个,每个3GB内存)上,该调用失败,错误为12“内存不足”。实际上,当我试图分配超过300MB的内存时,调用失败。313524224字节(299MB)有效,314572800字节(300MB)无效

问题是,同样的呼叫在第三台设备上工作,而第三台设备仍在安卓4.4.2上。更奇怪的是,这个调用可以在带有SDK 21(Android 5.0)的Android ARM模拟器上运行。不用说,同样数量的数据(不是mmap'ed)可以毫无问题地加载

dmesg向我报告:

<3>[ 1137.488411] [0:Thread-298: 4267] arch_get_unmapped_area (TASK_SIZE - len < addr) len=457232384 task size=3204448256 pid=4267 do_align=0 addr=3034054656 mmap_base=3069939712
编辑:

在@fadden回答的评论中,对我有效的解决方案


TL;DR:在
mmap()
失败后,将
dalvik.vm.heapsize
设置为
512m

转储
/proc/self/maps
的副本(只需从代码中打开文件并将内容复制到临时文件)。由于以下原因,获取大的连续虚拟地址范围时可能会遇到问题

Android中的一些Zip文件处理代码使用
mmap()
映射整个文件,并在内存中对其进行操作。有一天,有人创建了一个1GB的Zip文件,但无法打开它。虽然进程的虚拟地址空间有足够的空闲页,但没有足够的连续页来创建单个线性映射。(IIRC,解决方案是
mmap()


映射
输出将显示进程的地址空间。对于ASLR/碎片来说,300MB似乎有点低,但这是一个开始寻找的好地方,可能会解释不一致的行为。

Hi@fadden,感谢您的回答!我已经用/proc/self/maps更新了我的问题,我必须承认我不太习惯阅读这种输出,我希望你能帮助我理解它。左边的数字是十六进制的地址范围。0x00000000到0xBFFFFF可用于32位程序。粗略地看一下输出,内存中似乎有很多东西,dalvik区域的末尾是42c00000,而
HCLG.fst.map的开头是55281000。减去这些表示该区域约为294MB,因此300MB的分配将失败。(我不知道这是否是最大的连续开放空间,但它看起来像是更大的开放空间之一。)cf.Hi@fadden,再次感谢您的帮助。我用差距分析更新了我的问题,看来你是对的。在你看来,应该怎么做呢?看看你的细分,各种分配和碎片已经给你留下了大约700MB的可用虚拟地址空间,分成三块
mmap()
需要一个连续的地址区域。如果其中一些分配在您的控制之下,您可以尝试强制映射具有固定地址,以减少碎片,但这很少有好结果。您很可能需要找到一种减小映射区域大小的方法,例如,为file.interest的子部分创建单独的映射。这需要一个根设备,这限制了它对大多数应用程序作者的实用性,但对某些项目可能有帮助。
MappedFile* MappedFile::Map(istream* s, const FstReadOptions &opts,
                        size_t size) {
  size_t pos = s->tellg();

  if (opts.mode == FstReadOptions::MAP && pos >= 0 &&
      pos % kArchAlignment == 0) {
    int fd = open(opts.source.c_str(), O_RDONLY);
    if (fd != -1) {
      int pagesize = getpagesize();
      off_t offset = pos % pagesize;
      off_t upsize = size + offset;
      void *map = mmap(NULL, upsize, PROT_READ, MAP_SHARED, fd, pos - offset);
      char *data = reinterpret_cast<char*>(map);
      if (close(fd) == 0 && map != MAP_FAILED) {
        MemoryRegion region;
        region.mmap = map;
        region.size = upsize;
        region.data = reinterpret_cast<void*>(data + offset);
        MappedFile *mmf = new MappedFile(region);
        s->seekg(pos + size, ios::beg);
        if (s) {
          VLOG(1) << "mmap'ed region of " << size << " at offset " << pos
                  << " from " << opts.source.c_str() << " to addr " << map;
          return mmf;
        }
        delete mmf;
      } else {
        LOG(INFO) << "Mapping of file failed: " << strerror(errno);
      }
    }
  }
  // If all else fails resort to reading from file into allocated buffer.
  if (opts.mode != FstReadOptions::READ) {
    LOG(WARNING) << "File mapping at offset " << pos << " of file "
                 << opts.source << " could not be honored, reading instead.";
  }
  MappedFile* mf = Allocate(size);
  if (!s->read(reinterpret_cast<char*>(mf->mutable_data()), size)) {
    delete mf;
    return NULL;
  }
  return mf;
}
Gap between 00000000 and 12c00000 (diff = 314572800 bytes, 300 MB)
Gap between 42c00000 and 55281000 (diff = 308809728 bytes, 294.50390625 MB)
Gap between 67e80000 and 67ea4000 (diff = 147456 bytes, 0.140625 MB)
Gap between 7778b000 and 77800000 (diff = 479232 bytes, 0.45703125 MB)
Gap between 77a80000 and 77a82000 (diff = 8192 bytes, 0.0078125 MB)
Gap between 77c00000 and 77c04000 (diff = 16384 bytes, 0.015625 MB)
Gap between 78080000 and 780b7000 (diff = 225280 bytes, 0.21484375 MB)
Gap between 79ac1000 and 79ac2000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7db70000 and 7db71000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7e000000 and 7e001000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7e0fe000 and 7e0ff000 (diff = 4096 bytes, 0.00390625 MB)
Gap between 7e145000 and 7e146000 (diff = 4096 bytes, 0.00390625 MB)
Gap between b6fb9000 and be6ff000 (diff = 125067264 bytes, 119.2734375 MB)
Gap between beeff000 and ffff0000 (diff = 1091506176 bytes, 1040.94140625 MB)