地址空间
一、 早期系统与内存使用
-
早期系统内存模型:
-
操作系统占据物理内存的一部分 (如从地址0开始)。
-
运行的单个用户程序占据剩余物理内存 (如从64KB开始)。
-
抽象极少: 用户程序直接操作物理地址。
-
期望不高: 功能简单,开发者生活“轻松”。
-
二、 多道程序与时分共享的演进
-
多道程序 (Multiprogramming):
-
动机: 提高昂贵机器的CPU利用率。
-
实现: 多个进程准备运行,当一个进程等待I/O时,操作系统切换到另一个进程。
-
效率提升: 减少CPU空闲时间。
-
-
时分共享 (Time Sharing):
-
动机: 满足用户对交互性的需求,允许多个用户同时使用机器并获得及时响应。
-
早期粗糙实现:
-
一个进程独占内存运行一小段时间。
-
将其所有状态 (包括全部物理内存) 保存到磁盘。
-
加载另一个进程的状态运行。
-
问题: 速度太慢,尤其当内存增大时。
-
-
改进实现 :
-
多个进程(A、B、C)同时驻留在物理内存中,每个进程分配一小部分内存。
-
操作系统选择一个运行,其余等待。
-
新需求: 保护 (Protection)。防止进程间相互干扰内存。
-
-
三、 地址空间 (Address Space)
-
定义: 操作系统为运行程序提供的物理内存的抽象。是程序看到的内存视图。
-
核心作用: 理解内存虚拟化的关键。
-
地址空间的内容:
-
代码 (Code): 程序的指令,通常静态,位于地址空间特定区域 (如顶部)。
-
栈 (Stack):
-
保存当前函数调用信息、局部变量、参数、返回值。
-
通常从地址空间的一端开始,向特定方向增长 (如从底部向上增长)。
-
-
堆 (Heap):
-
用于动态分配、用户管理的内存 (如 malloc() 或 new)。
-
通常位于代码区之后,向与栈相反的方向增长 (如从代码区向下增长)。
-
-
其他: 静态初始化变量等。
-
-
地址空间的特性 :
-
是一个逻辑概念,程序认为自己拥有从0开始的一块连续内存。
-
栈和堆通常放置在两端,以便它们可以独立增长。
-
这种布局只是一种约定,多线程环境下可能不同。
-
四、 关键问题:如何虚拟化内存?
-
挑战: 操作系统如何在单一物理内存上,为多个共享内存的进程构建一个私有的、可能很大的地址空间的抽象?
-
虚拟化内存 (Virtualizing Memory):
-
程序以为自己加载到特定虚拟地址 (如0)。
-
操作系统和硬件配合,将虚拟地址转换为实际的物理地址。
-
例如:进程A尝试访问虚拟地址0,实际访问的是物理地址320KB。
-
五、 虚拟内存的目标
-
透明性 (Transparency):
-
运行程序不应感知到内存被虚拟化。
-
程序行为如同拥有私有物理内存。
-
操作系统和硬件在幕后完成复用和隔离。
-
-
效率 (Efficiency):
-
虚拟化应尽可能高效 (时间和空间)。
-
依赖硬件支持 (如 TLB)。
-
-
保护 (Protection):
-
进程间互相保护,操作系统也受保护。
-
进程不能访问其地址空间之外的内存。
-
实现进程间的隔离 (Isolation)。
-
六、 补充:你看到的所有地址都不是真的
-
C程序中打印出的指针地址、函数地址、栈变量地址等都是虚拟地址。
-
只有操作系统和硬件知道这些虚拟地址对应的物理地址。