升级到 Lollipop 后,Android NDK mmap 调用在 32 位设备上中断 [英] Android NDK mmap call broken on 32-bit devices after upgrading to Lollipop

查看:27
本文介绍了升级到 Lollipop 后,Android NDK mmap 调用在 32 位设备上中断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取 784 MiB 的内存.是的,我知道这对于 32 位手机来说很多,但以下调用在 Android 5.0 之前有效:

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);

但是,在来自不同制造商的三款不同设备上,升级到 Android 5.0 打破了这一点.我认为这是 5.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?

这是 logcat 中返回的错误消息:

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))

推荐答案

mmap()失败的地方,打开/proc/self/maps复制将内容复制到一个临时文件中,然后在编辑器中检查该文件.你应该看到一堆这样的条目:

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.

在上面的示例中,第一个条目的结尾 0x42c00000 和下一个条目的开头 0x55281000 之间存在很大的差距.大约是 294MB.接下来的两个之间没有空间,之后只有一个很小的空间.

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.

如果您查看您的流程图,并且没有发现足够大的间隙来容纳您的文件,那么您就有了答案.0x00000000 和 0xbfffffff 之间的区域通常可用于 32 位应用程序,但应用程序框架会占用大量空间.(前 1GB 映射到内核.)

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.)

我的猜测是 ASLR 和虚拟内存分配方式的某种组合棒棒糖导致了这个问题.在this similar question所附的地图中,发现的最大差距约为 300MB.有两个大的dalvik"区域,一个 768MB(在 12e01000),一个 1.2GB(在 84d81000).(由于您正在运行 Lollipop,这些实际上是由于 ART 而不是 Dalvik,但显然标签卡住了.)

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.)

一种可能性是 ART 比 Dalvik 对虚拟内存的要求更高,而且大的分配使应用程序难以获得大的映射区域.由于错误,ART 也可能过度分配.您可能想在 Marshmallow 上进行测试,看看是否有问题.

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.

无论如何,如果没有足够大的连续虚拟内存地址区域来容纳映射,则无法创建映射.在另一个问题中看到应用程序框架的使用和巨大的 ART 分配,即使虚拟地址空间没有碎片化,768MB 的映射也是不可能的.您将需要映射文件的较小部分,并可能在您努力腾出空间时取消映射它们.

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.

可能值得在 b.android.com 上提交一个错误.附上您的流程图文件的副本,并具体说明 Android 和设备的版本.

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.

有关解释/proc/maps 输出的更多信息,请参阅例如这个答案.

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

这篇关于升级到 Lollipop 后,Android NDK mmap 调用在 32 位设备上中断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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