- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
iOS的虚拟内存体使用量有上限吗?确定必须存在,但无法对其进行追踪。
最佳答案
tl; dr:
操作系统没有直接或明确的虚拟内存限制,因此理论上您的应用程序可以分配其整个潜在的逻辑地址空间。对于32位处理器,此大小为4 GB,对于64位处理器,此大小为18 exa。
实际上,可用虚拟内存大小存在局限性,这在很大程度上取决于应用程序如何使用其内存空间。这些限制源自操作系统管理虚拟内存的方式效率低下,因为针对低功耗(而不是繁重的文件I/O)进行了积极的操作系统调整。
如果您不在乎这些实际限制的详细信息,请随时在此处停止阅读。否则,以下是我在研究iOS上的内存问题以及虚拟内存和内存映射文件的入门方面的笔记,以及关于iOS与其他OS的不同之处的大量讨论。
什么是虚拟内存?
在包括iOS在内的现代操作系统中,您的进程可以访问的所有内存在技术上都是虚拟内存。之所以称为“虚拟”内存,是因为暴露给进程的地址空间(称为进程的逻辑地址空间)不一定与计算机的物理地址空间甚至其他进程的虚拟地址空间一致。虚拟内存允许内核在不同的上下文中提供不同的逻辑地址空间。
在iOS上,此逻辑地址空间的大小理论上仅受指针大小限制,该指针大小由处理器体系结构定义。这意味着进程在32位处理器上大约具有4 GB的逻辑存储空间,而在64位处理器上则具有18 EB的逻辑存储空间。
但是我的设备只有2GiB的RAM,如何实际使用18艾字节的存储空间?
要回答这个问题,首先您必须认识到,当您的进程调用诸如malloc
之类的东西来获取一些内存时,内核会在进程的逻辑地址空间中设置一小部分,并将其标记为已分配。在这种情况下,此分配的内存也占用物理内存空间。存储在物理内存中的数据称为驻留,因为它驻留在物理内存中,而驻留的数据被称为驻留集的一部分。内核通常通过跟踪进程的常驻集大小来将您的物理内存使用量与物理内存限制进行比较。
如果这是您的进程分配内存的唯一方法,那么对于大多数现代操作系统,您的进程将受到未分配物理内存量,机器页面文件,交换分区或其他一些可用空间的限制。非 volatile 后备存储。但是,iOS没有后备存储,它会强制执行strict constraints on the maximum resident set size of a process,因此通常,应用程序的常驻集大小将受到可用物理内存和每个进程常驻集限制中较小者的限制。
因此,如果分配内存永远都无法让您达到极限,那么为什么还要烦恼每个进程拥有18 EB的地址空间呢?
内存映射文件就是一个有用的例子。
当您有一个需要快速访问文件的应用程序并且想要依靠内核来确定要读取文件的哪些位以及何时读取时,可以对文件进行内存映射(请参阅 mmap
的文档)。在这种情况下,内核将文件(或您请求的文件的一部分)作为进程逻辑地址空间的连续区域呈现给您的进程。
内存映射文件如何工作?
操作系统将限制访问逻辑内存空间中为映射文件保留的部分,并在访问文件时将文件的大块透明地复制到物理内存中。这些“块”称为页面,而允许内核执行此操作的陷阱称为page fault
,而使数据驻留的行为称为分页输入,而从内存中删除页面的操作称为分页输出。所有这些使您的过程看起来就像您一直在内存中拥有已映射文件的区域(或整个文件,如果您要映射的是整个文件)。当然,为了使其正常工作,操作系统必须检测一段时间未访问的页面并将其分页出来。
iOS映射文件支持与其他操作系统有何不同?
在上述情况下,与大多数 table 面类操作系统相比,iOS有所限制。具体来说,从我在文档中看到的内容来看,似乎iOS上的页面只有使用PROT_READ
标志以只读方式映射时,才能从物理内存中清除。这意味着,如果您使用PROT_WRITE
标志映射文件,则该文件中的页面将保持驻留状态,直到您调用munmap
(我无法单独从文档中得知这是否意味着所有页面都将保持驻留状态,或者仅仅是修改后的页面,停在附近)。
此行为有别于其他操作系统,例如在PROT_WRITE
和MAP_SHARED
的情况下,可以随时清除未修改的页面,并且一旦它们与磁盘同步(即一旦它们不再“脏”),就可以清除未修改的页面。 )。同样在其他操作系统上,当使用PROT_WRITE
和MAP_PRIVATE
时,未修改页面的情况保持不变,但是只要OS使用某种“后备存储”(例如页面文件),仍可以从物理内存中清除已修改页面。
在后一种情况下,iOS无法分页这些修改,因为它没有后备存储。但是,我发现前一种情况令人困惑,因为从理论上讲,没有逻辑限制允许同步页面被调出。我最多可以推断的是,在PROT_WRITE
和MAP_SHARED
的情况下,这些页面将保持驻留状态,以避免在SMP环境中I/O调度程序和寻呼机之间的紧密同步。文档(下面的链接)中的一个较弱的建议支持这种推论,即在OSX上,无论页面是否与磁盘同步,修改后的页面都将被写入后备存储。但是,我打算对Mach内核进行更多阅读,以更全面地理解这些限制。
所以mmap
和PROT_READ
似乎是我们使用进程的所有可用VM空间而不达到常驻集大小限制的路径,对吗?我的意思是,理论上讲,使用这种方法,您可以多次创建一些大文件的只读映射,每个映射都占用您进程的可用逻辑内存空间的单独部分。在32位操作系统上,甚至在32位iOS上,您也可以很容易地通过虚拟地址空间饱和来实现您对世界支配的周密计划。大家的ENOMEM
!
因此,如果没有任何虚拟内存限制,为什么在我映射只读文件时我的应用程序被杀死?
实际上,虽然在许多操作系统上,您都可以mmap
一个文件,并且在OS知道细节的情况下放轻松,但在iOS上并非如此。即使只读映射文件在进程的逻辑地址空间中占主导地位,您的应用程序仍然有可能因为超过常驻设置的内存限制而被杀死。发生这种情况是因为内核决定了可以从物理内存中删除哪些页面的方式。
阅读下一部分时,请记住,iOS的电源效率已进行了非常积极的调整。它不是文件服务器。
内核只会释放已标记为不 Activity 的页面,我将从下面链接的文档中推断出,只有在某个阈值时间段内未触摸过的页面才能将页面标记为不 Activity 。
我还将根据文档和我自己的经验推断,负责标记页面处于非 Activity 状态的内核部分与负责检查驻留集大小限制的内核部分无法很好地协调。
当您的驻留集大小接近极限时,操作系统会尝试清除不 Activity 的页面,并发出内存警告,期望您的应用通过减小驻留集大小来对此做出响应。一旦您的居民集大小超过某个阈值,Jetsam就会杀死您的应用程序。
因此,鉴于上述情况,当您的应用程序对大量页面进行大量随机访问时,如果负责标记页面处于非 Activity 状态的内核部分没有运行一段时间,会发生什么情况?
即使您的大部分驻留集被只读映射文件的页面占用,您的应用也会被杀死。
我认为这是苹果建议尽可能使用更小,更瞬时的映射而不是映射整个文件的主要原因之一(尽管在这种使用模式下,内存空间碎片开始成为人们关注的问题)。
这个答案还不够长!我需要更多信息!
如果您想了解更多信息,请参阅virtual memory in iOS and OSX上的Apple文档以及memory mapped files section of the File System Advanced Programming Topics doc和 mmap
man page for iOS。
顺便说一句,还有一些其他相关主题值得阅读,这些主题使所有这些变得更加复杂和有用,例如页面锁定,页面同步,I/O缓存,预取,以及令人深为好奇的操作系统的运行方式。完成对共享映射的高效多处理访问。
关于ios - iOS的虚拟内存限制是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32664679/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!