什么是内存交换
进程必须在内存中以便执行。不过,进程可以暂时从内存交换到备份存储,当再次执行时再调回到内存中(图 1)。交换有可能让所有进程的总的物理地址空间超过真实系统的物理地址空间,从而增加了系统的多道程序程度。
图 1 使用磁盘作为存储仓库的两个进程的交换
系统维护一个可运行的所有进程的就绪队列,它们的映像在备份存储或内存中。当 CPU 调度器决定执行一个进程时,它调用分派器。分派器检查队列中的下一个进程是否在内存中。如果不在,并且没有空闲内存区域,那么分派器会换出当前位于内存中的一个进程,并换入所需进程,然后重新加载寄存器,并且将控制权转移到所选进程。
这种交换系统的上下文切换时间相当高。为了理解上下文切换时间的概念,我们举个例子,假设用户进程的大小为 100MB,并且备份存储是传输速度为 50MB/S 的标准硬盘。 100MB 进程传入或传出内存的时间为:
请注意,交换时间的主要部分是传输时间。总的传输时间与交换的内存大小成正比。如果我们有这样一个计算机系统,它的内存空间为 4GB,驻留的操作系统为 1GB,那么用户进程的最大大小为 3GB。然而,许多用户进程可能比这小得多,比方说,100MB。相比之下,100MB 的进程可以在 2s 内换出,而换出 3GB 需要 60s。显然,知道一个用户进程真正需要的内存空间而不是可能需要的内存空间,是非常有用的。
因此,只需要交换真正使用的内存,就可以减少交换时间。为有效使用这种方法,用户需要告诉系统它的内存需求情况。因此,具有动态内存需求的进程需要通过系统调用(request_memory() 和 release_memory())来通知操作系统它的内存需求变化情况。
交换也受到其他因素的约束。如果我们想要换出一个进程,那么应确保该进程是完全处于空闲的。特别关注的是任何等待 I/O。当需要换出一个进程以释放内存时,该进程可能正在等待 I/O 操作。然而,如果 I/O 异步访问用户内存的 I/O 缓冲区,那么该进程就不能换出。假定由于设备忙,I/O 操作在排队等待。如果我们需要换出进程 P1 而换入进程 P2,那么 I/O 操作可能试图使用现在已属于进程 P2 的内存。解决这个问题有两种主要方法:
现代操作系统现在并不使用标准交换。它的交换时间太多,提供的执行时间太少,不是合理的内存管理的解决方案。
然而,一些交换的变种却在许多系统中得以应用,包括 UNIX、Linux 和 Windows。一个常用的变种是:正常情况下,禁止交换;当空闲内存(未被操作系统或进程使用的内存)低于某个阈值时,启用交换。当空闲内存的数量增加了,就停止交换。
另一变种是交换部分进程(而不是整个进程),以降低交换时间。通常,这些交换的变种通常与虚拟内存一起工作。
移动设备通常采用闪存,而不是空间更大的硬盘作为它的永久存储。导致的空间约束是移动操作系统设计者避免交换的原因之一。其他原因包括:闪存写入次数的限制以及内存与闪存之间的吞吐量差。
当空闲内存降低到一定阈值以下时,苹果的 iOS,不是釆用交换,而是要求应用程序自愿放弃分配的内存。只读数据(如代码)可从系统中删除,以后如有必要再从闪存重新加载。已修改的数据(如堆栈)不会被删除。然而,操作系统可以终止任何未能释放足够内存的应用程序。
Android 不支持交换,而釆用类似 iOS 使用的策略。如果没有足够可用的空闲内存,则它可以终止进程。然而,在终止进程之前,Android 将其应用程序状态写到闪存,以便它能快速重新启动。
由于这些限制,移动系统的开发人员应小心分配和释放内存,以确保他们的应用程序不会使用太多内存或遭受内存泄漏。注意,iOS 和 Android 支持分页,所以他们确实有内存管理能力。
图 1 使用磁盘作为存储仓库的两个进程的交换
标准交换
标准交换在内存与备份存储之间移动进程,备份存储通常是快速磁盘,它应足够大,以容纳所有用户的所有内存映像的副本,并且它应提供对这些存储器映像的直接访问。系统维护一个可运行的所有进程的就绪队列,它们的映像在备份存储或内存中。当 CPU 调度器决定执行一个进程时,它调用分派器。分派器检查队列中的下一个进程是否在内存中。如果不在,并且没有空闲内存区域,那么分派器会换出当前位于内存中的一个进程,并换入所需进程,然后重新加载寄存器,并且将控制权转移到所选进程。
这种交换系统的上下文切换时间相当高。为了理解上下文切换时间的概念,我们举个例子,假设用户进程的大小为 100MB,并且备份存储是传输速度为 50MB/S 的标准硬盘。 100MB 进程传入或传出内存的时间为:
100MB/50MBps = 2s
交换时间为 2000ms。由于我们应换出和换入,总的交换时间约为 4000ms。(这里,我们忽略其他的磁盘性能问题)请注意,交换时间的主要部分是传输时间。总的传输时间与交换的内存大小成正比。如果我们有这样一个计算机系统,它的内存空间为 4GB,驻留的操作系统为 1GB,那么用户进程的最大大小为 3GB。然而,许多用户进程可能比这小得多,比方说,100MB。相比之下,100MB 的进程可以在 2s 内换出,而换出 3GB 需要 60s。显然,知道一个用户进程真正需要的内存空间而不是可能需要的内存空间,是非常有用的。
因此,只需要交换真正使用的内存,就可以减少交换时间。为有效使用这种方法,用户需要告诉系统它的内存需求情况。因此,具有动态内存需求的进程需要通过系统调用(request_memory() 和 release_memory())来通知操作系统它的内存需求变化情况。
交换也受到其他因素的约束。如果我们想要换出一个进程,那么应确保该进程是完全处于空闲的。特别关注的是任何等待 I/O。当需要换出一个进程以释放内存时,该进程可能正在等待 I/O 操作。然而,如果 I/O 异步访问用户内存的 I/O 缓冲区,那么该进程就不能换出。假定由于设备忙,I/O 操作在排队等待。如果我们需要换出进程 P1 而换入进程 P2,那么 I/O 操作可能试图使用现在已属于进程 P2 的内存。解决这个问题有两种主要方法:
- 不换出等待处理 I/O 的进程;
- I/O 操作的执行只能使用操作系统的缓冲。只有在进程换入时,操作系统缓冲与进程内存之间才能进行数据转移。注意,这种双缓冲本身增加了开销。我们现在需要再次复制数据,从内核内存到用户内存,然后用户进程可以访问它。
现代操作系统现在并不使用标准交换。它的交换时间太多,提供的执行时间太少,不是合理的内存管理的解决方案。
然而,一些交换的变种却在许多系统中得以应用,包括 UNIX、Linux 和 Windows。一个常用的变种是:正常情况下,禁止交换;当空闲内存(未被操作系统或进程使用的内存)低于某个阈值时,启用交换。当空闲内存的数量增加了,就停止交换。
另一变种是交换部分进程(而不是整个进程),以降低交换时间。通常,这些交换的变种通常与虚拟内存一起工作。
移动系统的交换
虽然用于 PC 和服务器的大多数操作系统支持一些交换的变形,移动系统通常不支持任何形式的交换。移动设备通常采用闪存,而不是空间更大的硬盘作为它的永久存储。导致的空间约束是移动操作系统设计者避免交换的原因之一。其他原因包括:闪存写入次数的限制以及内存与闪存之间的吞吐量差。
当空闲内存降低到一定阈值以下时,苹果的 iOS,不是釆用交换,而是要求应用程序自愿放弃分配的内存。只读数据(如代码)可从系统中删除,以后如有必要再从闪存重新加载。已修改的数据(如堆栈)不会被删除。然而,操作系统可以终止任何未能释放足够内存的应用程序。
Android 不支持交换,而釆用类似 iOS 使用的策略。如果没有足够可用的空闲内存,则它可以终止进程。然而,在终止进程之前,Android 将其应用程序状态写到闪存,以便它能快速重新启动。
由于这些限制,移动系统的开发人员应小心分配和释放内存,以确保他们的应用程序不会使用太多内存或遭受内存泄漏。注意,iOS 和 Android 支持分页,所以他们确实有内存管理能力。
所有教程
- C语言入门
- C语言编译器
- C语言项目案例
- 数据结构
- C++
- STL
- C++11
- socket
- GCC
- GDB
- Makefile
- OpenCV
- Qt教程
- Unity 3D
- UE4
- 游戏引擎
- Python
- Python并发编程
- TensorFlow
- Django
- NumPy
- Linux
- Shell
- Java教程
- 设计模式
- Java Swing
- Servlet
- JSP教程
- Struts2
- Maven
- Spring
- Spring MVC
- Spring Boot
- Spring Cloud
- Hibernate
- Mybatis
- MySQL教程
- MySQL函数
- NoSQL
- Redis
- MongoDB
- HBase
- Go语言
- C#
- MATLAB
- JavaScript
- Bootstrap
- HTML
- CSS教程
- PHP
- 汇编语言
- TCP/IP
- vi命令
- Android教程
- 区块链
- Docker
- 大数据
- 云计算