内存管理 物理内存 虚拟内存管理
第四章内存管理
嵌入式操作系统原理
——Windows CE
内存管理
? 物理内存
? 虚拟内存
? 内存分配方式
? 管理低内存状态
? ROM
? RAM
1. 物理内存
1.1 ROM
? 存储操作系统及与系统绑定的应用程序
? ROM中程序的两种执行方式
– 本地执行(XIP)
– 非本地执行
? config.bib文件的MEMORY部分指出了
ROM和RAM在虚拟地址空间中的位置
BIB文件和ROM
BIB文
件
MEMORY部分
起始
地址
区域
名称
区域字
节数
区域
类型
1.2 RAM
? 程序内存
? 对象存储
– 文件系统
– 系统注册表
– Windows CE数据库
RAM
对象存储
程序内存
相当于永久存储器,即使在系统关闭后其内
容仍然保留
?对象存储和程序内存的边界可以移动
?用户可使用System Control panel应用程序
来移动边界
相当于PC上的RAM,用于程序运行
2. 虚拟内存
? 虚拟内存基础
? 分页内存系统
? 虚拟内存术语
? Windows CE的虚拟地址空间
– 内核空间
– 用户空间
? 和Windows XP的比较
? 在Platform Builder中查看关于内存的信息
2.1 虚拟内存基础
? 当MMU (Memory Management Unit)可用
时,虚拟地址是CPU引用的任何地址
? 虚拟地址必须映射到实际的物理地址来识
别物理资源,如ROM、RAM、Flash、
CPU寄存器、片上系统原件、总线映射原
件等
? CPU通常不直接存取物理地址,除了MMU
尚未使能的情况下
2.2 分页虚拟内存系统
? 微处理器管理的最小内存单元是―页‖,
当应用程序访问页面时,微处理器把页面
的虚拟地址转化成物理资源中的物理地址。
? Windows CE.NET实现了一个分页虚拟内
存系统,根据微处理器的不同,分页为1KB
或4KB的大小
2.3 虚拟内存术语
? 静态映射虚拟地址
– 虚拟-物理映射从不改变
? 动态映射虚拟地址
– 虚拟-物理映射可以改变
2.4 虚拟地址空间
? 虚拟内存管理
– Windows CE .NET 提
供了一个4GB(32位)
的虚拟地址空间
– 大多低2GB的虚拟地
址都是动态映射,一
些高2GB的虚拟地址
是动态映射
内核地址空间
(2GB)
用户地址空间
(2GB)
0x0000 0000
0x7FFF FFFF
0xFFFF FFFF
0x8000 0000
32位虚
拟地址
空间
内核地址空间
Kernel Addresses: KPAGE
Trap area,others
Statically mapped virtual
address: OEM additional
Statically mapped virtual
addresses: CACHED
Slot97:NK.exe(Secure slot)
Statically mapped virtual
addresses: UNCACHED
Unused
0x8000 0000
0xA000 0000
0xC000 0000
0xC200 0000
0xC400 0000
0xE000 0000
0xFFFF FFFF
最大512MB
的物理资源
可以映射到
主要的静态
映射区域
物理内存和内核虚拟地址的映射
用户地址空间
Slot63
Slot62
Slot32
Slot1
Slot0
0x0200 0000
0x7FFF FFFF
0x0000 0000
每个槽32MB
分成了64个槽
Slot2
Slot30
前33个槽对应
33个进程
用户地址空间
Slot33-62
对象存储&内存映射文件
Slot1:XIP DLLs
Slot0:当前进程
0x0200 0000
0x7FFF FFFF
0x0000 0000
Slot2-32
进程
Slot63:Resource Mappings
0x4200 0000
当前进程的拷贝
同时可运行32个
进程
?对象存储受保护
?所有的线程均可
存取内存映射文件
所有线程均可存取
DLL资源
进程槽
? 被分成512个大小为64KB的块
? 根据CPU的不同,每个块被分成1KB或4KB
的页面,这些页面映射到物理内存
? 页面的三种状态
– 空闲
– 保留
– 提交
应用程序的虚拟地址空间
0x0000 0000
COREDELL.DLL
Other XIP DLLs
XIP DLL空间
基于RAM的DLLs
可用虚拟地址空间
堆栈(保留空间)
资源
堆(保留空间)
读写数据
只读数据
代码
保留
0x0001 0000
0x0200 0000
0x03FF FFFF
DLL空间
(对所有应用程序持
续可用)
应用程序空间
(拷贝到slot0)
从对象存储区加载的 DLL
从 ROM 解压缩的 DLL
从外部文件系统加载的 DLL
2.5 和Windows XP的比较
0x0000 0000
0x8000 0000
0xFFFF FFFF
0xFFFF FFFF
0x8000 0000
0x0000 0000
0x4200 0000
0x4000 0000
Windows XP
Windows CE
2.6 在Platform Builder中查看关
于内存的信息
页面大小
4KB
进程槽的
内存分配
情况
MI FULL
命令
在Platform Builder中查看关于内
存的信息(续)
窗口
显示所有加载模块(DLL文件和EXE文件)的地址范围
对EXE文件数据和代码包含在同一地址范围内
对DLL文件,代码和数据是分开的,所以在Slot0有重定位数据地址
在Platform Builder中查看关于内
存的信息(续)
进程地址指出
了其对应的进
程槽
进程窗口
在Platform Builder中查看关于内
存的信息(续)
工具可以列出.BIN文件中包含的模块和文件
部分显示了一些全局值
3 内存分配方式
? 虚拟内存
? 堆
? 堆栈
? 静态数据
? 字符串资源
? 选择合适的内存类型
3.1 使用虚拟内存
? 虚拟内存API的形式:Virtualxxxxx()
? 用于分配大块的内存(通常是整数个页面)
? 其优点是不产生碎片
? 用户要确保有效使用虚拟内存
? 管理内存映射需要轻微的消耗
虚拟内存管理函数
函数 功能
VirtualAlloc 保留和提交虚拟内存
VirtualQuery 提供虚拟内存页的状态信息
VirtualProtect 改变提交页面的访问权限
VirtualFree 释放虚拟内存
VirtualCopy 绑定指定的物理内存地址范围到
静态映射虚拟地址
虚拟内存分配
VirtualAlloc函数分配内存的过程分为两个步骤
? 第一步:保留虚拟内存空间的区域
– 不会消耗任何RAM;只是防止一部分虚拟地址空
间被用于其他用途
– 保留的空间将圆整到64KB
? 第二步:提交部分或整个区域
– 指将实际物理内存映射到保留区域
虚拟内存分配
LPVOID VirtualAlloc(
LPVOID lpAddress, //虚拟地址
DWORD dwSize, //区域大小
DWORD flAllocationType,//分配的类型
DWORD flProtect //访问保护
);
分配的类型
值 说明
MEM_COMMIT 分配程序使用的内存
MEM_RESERVE 保留要随后提交的虚拟地址空间
MEM_AUTO_COMMI
T
在第一次访问块中的每个页面时,
该页面仍由系统自动提交
MEM_TOP_DOWN
将内存尽可能映射到最高的允许
虚拟地址
访问保护标志
PAGE_READONLY--------------------区域只读
PAGE_READWRITE------------------可读写区域
PAGE_EXECUTE----------------------区域包含可执行代码
PAGE_EXECUTE_READ--------------区域包含可执行代码,
且应用程序可读此区域
PAGE_EXECUTE_READWRITE ------区域包含可执行代码,
且应用程序可读写此区域
PAGE_GUARD-------------------------首次访问此区域将导致
STATUS_GUARD_PAGE异常
PAGE_NOACCESS---------------------任何访问均将导致访问冲突
PAGE_NOCACHE----------------------微处理器不会高速缓存映射到
这个区域的RAM页面
限制因素
? 应用程序的32 MB 虚拟地址空间
? 分配时尽管是以字节为单位,但系统会圆整到下
一个页面的边界提交
? 分配时保留的空间将圆整到64KB,而不是在分配
函数中指定的大小
? 举例:假定要分配512个页面(4KB页面系统上)
– 代码段一:错误的方法
– 代码段二:正确的方法
代码段一
INT i;
PVOID pMem[512];
for (i = 0; i 管理的
保留的虚拟内存空间区域
? 应用程序的第一个堆由系统创建,称之为
本地堆
? 默认情况下,Windows CE最初保留192KB
用于本地堆,但仅当他们被分配时才会提
交页面
? 应用程序可以创建一个单独的堆
使用本地堆
? 系统会自动查找未保留的内存,增加堆的
大小以满足需求,增加的内存和之前的内
存在物理空间上可能不连续
? Windows CE只支持堆中固定块的分配,这
样随着时间的推移就会产生碎片
? 当堆中的块被释放时,系统将查看是否整
个页都已经被释放,如果是那个页将被回
收
管理本地堆的函数
? LocalAlloc,在本地堆分配指定字节大小的
内存块
? LocalLock,将内存句柄转换成内存指针
? LocalSize,查询当前内存大小
? LocalReAlloc,重新分配内存(调整大小或
属性)
? LocalFree,释放堆中的内存
在本地堆中分配内存
? 可以在堆中分配4或8字节的内存单元(由
CPU决定)
? 堆中分配大于192KB的单元仍然调用
VirtulAlloc实现
? 使用完后注意要回收分配的内存
LocalAlloc函数
HLOCAL LocalAlloc(
UINT uFlags, //块的特征
UINT uBytes //要分配的字节
);
uFlags的值 意义
LMEM_FIXED 在堆中分配固定大小的块
LMEM_ZEROINIT 将内存的内容初始化为0
LPTR LMEM_FIXED和LMEM_ZEROINIT的组合
使用单独的堆
HeapCreate 创建一个单独的堆
HeapAlloc 在堆中分配内存
HeapFree 释放单独的堆中的内存
HeapReAlloc 调整单独的堆中的内存大小
HeapSize 确定块的实际大小
HeapDestroy 破坏一个单独的堆
GetProcesssHeap 返回调用DLL的进程的本地堆的句柄
3.3 使用堆栈
? 堆栈是函数使用的变量的存储区域
? 每个线程都有一个堆栈,线程开始时由系
统创建
? 线程堆栈的大小默认为64KB,可以通过使
用/STACKSIZE链接程序开关来调整
? 创建线程是可以更改其堆栈的大小
? 不要在低内存情况下使用大量堆栈
3.4 静态数据
? Windows CE为应用程序的静态数据分配了
两个RAM块
– 用于读取/写入数据
– 用于只读数据
? 以页面为单位来分配
? 好的应用程序应该能确保只有很少或根本
没有额外的剩余空间
3.5 字符串资源
? 当特定语言的信息被保留在编译代码之外时,字
符串资源是减少应用程序所占用内存的一种较好
的方法
? LoadString函数用于从资源中加载字符串
? 在Windows CE下,如果LoadString函数中的参数
lpBuffer是NULL,则返回一个指向字符串的只读
指针作为返回值,将其放入常量统一代码字符串
中,而不需要分撇一个缓冲区来保存字符串,并
在需要的时候就可以使用
3.6 选择正确的内存类型
直接分
配内存
类型
?对于大的内存块,最好是直接分配虚拟内存
?是最灵活的内存分配类型
?担心页面的粒度并跟踪保留页面和提交页面的情况
本地堆
?使用便利,不需要要创建
?在必需的时候它会按需求来增大
?产生碎片
单独
的堆
?在它们的时间到了以后能破坏它们(将内存碎片问
消灭在萌牙
状态
?必须手工创建和破坏他们
堆栈
?易于使用并且随处可用
?需些考虑的是堆栈的最大大小和在低内存条件下扩大堆栈的问题
静态
数据
?完全自由地移进一个或两个缓冲区,因为该页面总是要分配的
?常量数据越多越好,因为不占用RAM
4 管理低内存状态
? WM_HIBERNATE消息
– 当可用内存很少时以Z轴反方向发送到应用程序
– 应用程序接到此消息后应该尽可能减少占用的内存
? 释放高速缓存中的数据
? 释放任意GDI对象,如字体、位图、画笔等
? 破环任意窗口控件
? Windows CE定义的四种内存状态
– 正常
– 受限
– 低
– 临界
? 具体系统处理低内存的策略有所不同
– Explorer Shell和Pocket PC处理低内存的策略比较
Explorer Shell处理低内存的策略
事件
空闲内存
(1024B页面)
空闲内存
(4096B页面)
注释
受限内
存状态
128KB 160KB
以z轴反方向顺序将
WM_HIBERNATE消息发
送到应用程序。必要时释
放回收的堆栈空间
低内存
状态
64KB 96KB
将虚拟分配限制为16KB。
显示低内存对话框
临界内
存状态
16KB 48KB 将虚拟分配限制为8KB
Pocket PC处理低内存的策略
事件
空闲内存
(1024B页面)
空闲内存
(4096B页面)
注释
休眠
阈值
200KB 224KB
以z轴反方向顺序将
WM_HIBERNATE消息发
送到应用程序
受限内
存状态
128KB 160KB
以z轴反方向顺序关闭应用
程序。必要时释放回收的
堆栈空间
低内存
状态
64KB 96KB
将虚拟分配限制为16KB。
显示低内存对话框
临界内
存状态
16KB 48KB 将虚拟分配限制为8KB
其它
? 对于简单外壳的Windows CE版本,应用程序应
该设计自己的管理低内存状况的策略。
? 一定要检查从分配内存调用返回的代码
? 关于Win32内存管理API参考书
– Programming Applications for Microsoft Windows
– By Jeff Richter
– Microsoft Press,1999
? 物理内存
– ROM
– RAM
? 虚拟内存
– 虚拟内存基础
– 分页内存系统
– 虚拟内存术语
– Windows CE的虚拟地址
空间
– 和Windows XP的比较
– 在Platform Builder中查看
关于内存的信息
? 内存分配方式
– 虚拟内存
– 堆
– 堆栈
– 静态数据
– 字符串资源
– 选择合适的内存类型
? 管理低内存状态
– WM_HIBERNATE消息
– Windows CE定义的四种内
存状态
– 具体系统处理低内存的策略
有所不同
资源
? Programming Microsoft Windowss CE.NET 3rd edition,
Douglas Boling,Microsoft Press,2003
? 《Windows CE.NET系统分析及试验教程》,陈向群王
雷马洪兵向勇等编著,机械工业出版社,2003
? Windows CE.NET help
? MSDN library
? Microsoft Windows CE.NET train: 2540_Developing
Embedded Solutions for Windows CE .NET
? 《Windows CE.NET内核定制及应用开发》,周毓林宁
杨陆贵强付林林编著,电子工业出版社,2005