的Andr​​oid NDK MMAP调用上破32位设备升级到棒棒糖后 [英] Android NDK mmap call broken on 32-bit devices after upgrading to Lollipop

查看:795
本文介绍了的Andr​​oid NDK MMAP调用上破32位设备升级到棒棒糖后的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图抓住784 MIB的内存。是的,我知道这是一个很大的一个32位的手机,而Android 5.0之前,下面的调用工作:

 的mmap(0,0x31000000,PROT_NONE,MAP_ANON | MAP_SHARED,-1,0);
 

然而,来自不同制造商三种不同的设备,升级至Android 5.0已经打破了这一点。我想这是在5.0内存分配的功能有所改变;也许不同的标志需要传递?

下面是在logcat中返回的错误信息:

  E /的libc:MMAP失败(PID 9994,TID 10125,大小822083584,标志为0x21,错误号12(内存不足))
 

解决方案

在其中的mmap()失败,打开的/ proc点/自/图的内容复制到一个临时文件,然后检查在编辑器中的文件。你应该看到一堆的条目是这样的:

  12e01000-42c00000 --- p 00201000 00:04 11639的/ dev / ashmem /达尔维克主要空间(删除)
55281000-5d500000  -  [R  -  S 00000000 00:16 61 /存储/ sdcard1 /等等
5d500000-67e80000 RW-P 00000000 00:00 0 [匿名:libc_malloc]
67ea4000-682cc000 R-XP 00000000 B3:17 114807 /system/vendor/lib/libsc-a3xx.so
682cc000-682f4000  -  [R  -  P 00427000 B3:17 114807 /system/vendor/lib/libsc-a3xx.so
 

左侧的数字是虚拟地址范围(开始/结束)的过程。当你创建一个新的映射,​​它需要适合映射之间的差距。

在上面的例子中,出现的第一个条目月底在0x42c00000和下开始在0x55281000之间的一个不错的大缺口。这是约294MB。有接下来的两个之间没有空间,并且只有一个小的后

如果你看看你的过程图,并没有找到足以容纳你的文件有差距,你有你的答案。 00000000和0xbfffffff之间的区域,一般适用于32位应用程序,但应用程序框架使用了一个大便宜呢。 (顶1GB映射到内核。)

我的猜测是, ASLR 和变化的方式虚拟内存分配棒棒糖导致此问题。在连接到这个类似的问题地图,发现的最大差距约为300MB。有两个大的Dalvik区域,一个768MB(在12e01000),一个1.2GB(在84d81000)。 (因为你正在运行棒棒糖,这些其实都是因为艺术而不是Dalvik的,但显然标签卡住了。)

一种可能性是,艺术比的Dalvik没有更高的虚拟内存的要求,大分配是难以让应用程序能够获得较大的映射区域。这也有可能是ART是过度分配由于存在错误。你可能想测试的棉花糖,看看如果事情得到了解决。

无论是哪种情况,你无法创建一个映射,如果没有一个连续的虚拟内存地址区域大得足以容纳它。与应用程序框架使用情况和出现在其他问题的巨大技术分配,一个768MB映射将是不可能的,即使没有被片段化的虚拟地址空间。您将需要映射文件更小的部分,并有可能取消映射他们为你工作,以腾出空间。

这可能是值得提起的 b.android.com 的错误。附上你的过程图文件的副本,并具体指出,Android版本和设备。

有关更多一点关于跨preting的/ proc /图输出,如见这个答案

I'm trying to grab 784 MiB of memory. Yes, I know that is a lot for a 32-bit phone, but the following call worked before Android 5.0:

mmap(0, 0x31000000, PROT_NONE, MAP_ANON | MAP_SHARED, -1, 0);

However, on three different devices from different manufacturers, upgrading to Android 5.0 has broken this. I assume this is some change in memory allocation functionality in 5.0; maybe different flags need to be passed in?

Here's the error message returned in logcat:

E/libc﹕ mmap fail (pid 9994, tid 10125, size 822083584, flags 0x21, errno 12(Out of memory))

解决方案

At the point where the mmap() fails, open /proc/self/maps and copy the contents to a temp file, then examine the file in an editor. You should see a bunch of entries like this:

12e01000-42c00000 ---p 00201000 00:04 11639      /dev/ashmem/dalvik-main space (deleted)
55281000-5d500000 r--s 00000000 00:16 61         /storage/sdcard1/blah
5d500000-67e80000 rw-p 00000000 00:00 0          [anon:libc_malloc]
67ea4000-682cc000 r-xp 00000000 b3:17 114807     /system/vendor/lib/libsc-a3xx.so
682cc000-682f4000 r--p 00427000 b3:17 114807     /system/vendor/lib/libsc-a3xx.so

The numbers on the left are virtual address ranges (start / end) for the process. When you create a new mapping, it needs to fit in the gap between mappings.

In the example above, there's a nice big gap between the end of the first entry at 0x42c00000 and the start of the next at 0x55281000. That's about 294MB. There's no space between the next two, and only a small one after that.

If you look at your process map, and don't find a gap big enough to hold your file, you have your answer. The region between 0x00000000 and 0xbfffffff is generally available to 32-bit apps, but the app framework uses up a great deal of it. (The top 1GB is mapped to the kernel.)

My guess is that some combination of ASLR and changes to the way virtual memory is allocated in Lollipop have led to this problem. In the map attached to this similar question, the largest gap found was about 300MB. There are two large "dalvik" regions, one 768MB (at 12e01000), one 1.2GB (at 84d81000). (Since you are running Lollipop these are actually due to ART rather than Dalvik, but apparently the label stuck.)

One possibility is that ART has higher virtual memory requirements than Dalvik did, and the large allocations are making it difficult for applications to get large mapped regions. It's also possible that ART is over-allocating due to a bug. You may want to test on Marshmallow to see if something got fixed.

Whatever the case, you can't create a mapping if there isn't a contiguous virtual memory address region large enough to hold it. With the app framework usage and the enormous ART allocations seen in the other question, a 768MB mapping wouldn't be possible even if the virtual address space weren't fragmented. You will need to map smaller sections of the file, and possibly un-map them as you work to make room.

It might be worth filing a bug on b.android.com. Attach a copy of your process map file, and be specific about version of Android and device.

For a bit more about interpreting /proc/maps output, see e.g. this answer.

这篇关于的Andr​​oid NDK MMAP调用上破32位设备升级到棒棒糖后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆