基本概念
内存管理基础
内存管理是操作系统的核心功能之一,负责管理计算机的主存储器,为进程分配和回收内存空间,确保内存的安全使用。
程序装入与链接
程序装入过程
程序从外存调入内存的过程称为程序装入,主要包括以下步骤:
- 编译阶段:将源代码编译成目标代码
- 链接阶段:将多个目标模块链接成可执行程序
- 装入阶段:将可执行程序装入内存
链接方式
1. 静态链接
// 编译时链接所有库函数
gcc -static program.c -o program
- 优点:执行速度快,不依赖外部库
- 缺点:可执行文件大,内存利用率低
2. 动态链接
// 运行时链接库函数
gcc program.c -o program
- 优点:节省内存,便于库函数更新
- 缺点:执行速度稍慢,依赖外部库
3. 运行时动态链接
// 程序运行时根据需要加载库
dlopen("libmath.so", RTLD_LAZY);
装入方式
1. 绝对装入
- 程序装入到指定的绝对地址
- 适用于单道程序系统
- 地址在编译时确定
2. 可重定位装入
- 程序装入到内存的任意位置
- 需要重定位寄存器
- 支持多道程序设计
3. 动态运行时装入
- 程序在运行时才确定装入位置
- 支持虚拟内存管理
- 地址转换延迟到访问时进行
逻辑地址与物理地址空间
地址空间概念
逻辑地址空间:
- 由 CPU 生成的地址
- 从 0 开始的连续地址空间
- 程序员可见的地址
物理地址空间:
- 内存单元的实际地址
- 可能不连续
- 硬件可见的地址
地址转换过程
逻辑地址 → 地址转换机构 → 物理地址
地址转换机构:
- 重定位寄存器:基址寄存器
- 页表:分页系统中的地址映射
- 段表:分段系统中的地址映射
地址转换示例
基址重定位:
// 逻辑地址:1000
// 基址寄存器:5000
// 物理地址 = 逻辑地址 + 基址 = 1000 + 5000 = 6000
分页地址转换:
// 逻辑地址:0x1234
// 页号:0x12,页内偏移:0x34
// 通过页表查找物理块号
// 物理地址 = 物理块号 × 页大小 + 页内偏移
内存保护
保护机制
1. 界限寄存器保护
// 基址寄存器:5000
// 界限寄存器:2000
// 有效地址范围:[5000, 7000)
if (address < base || address >= base + limit) {
// 地址越界,产生保护性中断
raise_protection_fault();
}
2. 页表保护位
typedef struct {
int frame_number; // 物理块号
int valid; // 有效位
int read; // 读权限
int write; // 写权限
int execute; // 执行权限
} PageTableEntry;
3. 段表保护位