Windows内存管理机制

合集下载

Windows核心编程-内存管理

Windows核心编程-内存管理

使用虚拟内存



虚拟内存,最适合用来管理大型对象或 结构数组。 内存映射文件,最适合用来管理大型数 据流(通常来自文件)以及在单个计算 机上运行的多个进程之间共享数据。 内存堆栈,最适合用来管理大量的小对 象。
使用虚拟内存-VirtualAlloc
通过调用Vi r t u a l A l l o c函数,可以在进程的地址空间 中保留一个区域: LPVOID VirtualAlloc(
内存管理

当一个进程中的线程试图将数据写入一个共享内存块 时,系统就会进行干预,并执行下列操作步骤:



1) 系统查找R A M中的一个空闲内存页面。注意,当该模块 初次被映射到进程的地址空间时,该空闲页面将被页文件 中已分配的页面之一所映射。当该模块初次被映射时,由 于系统要分配所有可能需要的页文件,因此这一步不可能 运行失败。 2) 系统将试图被修改的页面内容拷贝到第一步中找到的页 面。该空闲页面将被赋予PA G E _ R E A D W R I T E或 PA G E _ E X E C U T E _ R E A D W R I T E保护属性。 原始页面的保护属性和数据不发生任何变化。 3) 然后系统更新进程的页面表,使得被访问的虚拟地址被 转换成新的R A M页面。
使用虚拟内存-提交


始终设法进行物理存储器的提交。每次调用Vi r t u a l A l l o c函数的时候,不要查看物理存储器是否已经映 射到地址空间区域的一个部分,而是让你的程序设法 进行内存的提交。系统首先查看内存是否已经被提交, 如果已经提交,那么就不要提交更多的物理存储器。 这种方法最容易操作,但是它的缺点是每次改变C E L L D ATA结构时要多进行一次函数的调用,这会使程 序运行得比较慢。 使用Vi r t u a l Q u e r y函数确定物理存储器是否已经 提交给包含C E L L D ATA结构的地址空间。如果已经 提交了,那么就不要进行任何别的操作。如果尚未提 交,则可以调用Vi r t u a l A l l o c函数以便提交内存。 这种方法实际上比第一种方法差,它既会增加代码的 长度,又会降低程序运行的速度(因为增加了对Vi r t u a l A l l o c函数的调用)。

windows heapalloc和heapfree 原理

windows heapalloc和heapfree 原理

windows heapalloc和heapfree 原理
Windows的HeapAlloc和HeapFree是用于在进程的堆中分配和释放内存块的函数。

堆是进程用来存储动态分配的内存的一种数据结构,每个进程都有一个独立的堆。

HeapAlloc函数通过系统调用HeapCreate来创建进程的堆,调用者指定了所需内存块的大小和一些标志。

系统会根据需要从进程空间中的堆中分配出一块足够大的内存,然后把这块内存标记为已分配。

如果堆没有足够的连续内存来满足请求,系统会进行相应的内存管理操作,例如从操作系统申请更多内存。

HeapFree函数用于释放已分配的内存块,调用者需要指定要释放的内存块的地址。

系统会将指定的内存块标记为未分配,然后根据需要进行合并操作,以便将相邻的未分配的内存块合并成一个更大的内存块。

HeapAlloc和HeapFree的实现涉及到底层的内存管理机制,包括虚拟内存管理和物理内存管理。

Windows使用虚拟内存机制来为每个进程提供一种看似连续的地址空间,而实际上这些地址可能对应于不连续的物理内存页。

当HeapAlloc调用时,系统会根据虚拟内存空间的情况来选择一个合适的物理内存页来分配内存。

类似地,当HeapFree调用时,系统会将释放的内存标记为未分配,并可能触发相应的内存管理操作,例如将物理内存页返回给操作系统。

总而言之,Windows的HeapAlloc和HeapFree通过调用底层的内存管理机制来实现动态分配和释放内存的功能,涉及到虚
拟内存管理和物理内存管理等复杂的操作。

这些函数的具体实现细节由操作系统负责,开发者只需要使用它们来申请和释放内存块。

windows操作系统原理

windows操作系统原理

windows操作系统原理Windows操作系统原理是指Windows操作系统设计与实现的基本原理和机制。

Windows操作系统是由微软公司开发的一种面向个人计算机的操作系统。

Windows操作系统的原理包括以下几个方面:1. 多任务管理:Windows操作系统采用了抢占式的多任务处理机制,通过任务调度器来管理多个任务的执行。

每个任务独立运行在自己的进程中,操作系统根据进程的优先级和时间片来进行任务调度。

2. 内存管理:Windows操作系统使用虚拟内存管理机制,将物理内存划分为多个页框,每个进程有自己的虚拟地址空间。

操作系统通过分页机制将虚拟内存映射到物理内存中,以便实现进程间的隔离和保护。

3. 文件系统:Windows操作系统使用NTFS文件系统作为默认的文件系统。

NTFS文件系统支持文件和目录的权限控制、文件压缩和加密等功能。

4. 设备管理:Windows操作系统通过设备驱动程序来管理硬件设备。

每个设备驱动程序负责与特定设备的通信,并提供统一的接口供应用程序调用。

5. 网络通信:Windows操作系统支持TCP/IP协议栈,并提供了各种网络通信服务,如网络协议栈、网络接口、套接字接口等,以实现应用程序之间的网络通信。

6. 用户界面:Windows操作系统提供了图形用户界面(GUI),包括窗口管理、菜单、对话框等,使得用户可以通过鼠标、键盘等输入设备与计算机进行交互。

7. 安全性:Windows操作系统通过用户账户和权限管理来保护系统和用户数据的安全性。

每个用户都有自己的账户,并且可以通过权限控制来限制对文件和系统资源的访问。

这些原理和机制共同构成了Windows操作系统的核心。

通过合理地设计和实现,Windows操作系统能够提供稳定、安全、高效的计算环境,满足用户的各种需求。

如何管理Windows10的虚拟内存

如何管理Windows10的虚拟内存

如何管理Windows10的虚拟内存
Windows 10 的虚拟内存用久了也会出现一些问题,那么如何管理Windows 10 的虚拟内存的呢?下面是店铺收集整理的如何管理Windows 10 的虚拟内存,希望对大家有帮助~~
管理 Windows 10 的虚拟内存的方法
工具/原料
Windows 10 专业版。

方法/步骤
打开设置窗口。

“开始”-->“设置”。

进入性能调整选项窗口。

在设置窗口里,输入“性能”,然后在窗口筛选出来的列表里,点选“调整 Windows 的外观和性能”。

在弹出的“性能选项”窗口里,点选“高级”选项卡。

在“高级”选项卡中,点击“虚拟内存”里的“更改”。

在接下来的窗口中,查看窗口下方关于当前虚拟内存分配的情况,特别是“推荐”和“当前已分配”这两个值。

如果确定是当前分配值过低导致电脑性能出现问题,可以取消对“自动管理分页文件的大小”选项,然后在“自定义大小”中,输入你要设置的最大和最小值。

其中最小值可以是第5 步骤中的“推荐”值,当然最大值更要比它大了。

重启计算机,上述设置就会生效。

如果重启之后,觉得计算机性能没有提升或甚至出现了倒退,可以按上述步骤,将虚拟内存恢复成让系统自动管理。

如何管理 Windows 10 的虚拟内存。

Windows堆的数据结构与管理策略

Windows堆的数据结构与管理策略

堆(heap)是一种内存管理器,程序可以通过堆来动态地分配和释放内存。

通常,需要使用堆的情况包括,当无法预先知道所需的内存大小或者所需内存过大而无法在栈中进行分配。

操作系统提供一套API把复杂的堆管理机制屏蔽掉。

下面是一些与堆相关的APIFunction DescriptionGetProcessHeap Obtains a handle to the heap of the calling process.GetProcessHeaps Obtains handles to all of the heaps that are valid for the calling process. HeapAlloc Allocates a block of memory from a heap.HeapCompact Coalesces adjacent free blocks of memory on a heap.HeapCreate Creates a heap object.HeapDestroy Destroys the specified heap object.HeapFree Frees a memory block allocated from a heap.HeapLock Attempts to acquire the lock associated with a specified heap. HeapQueryInformation Retrieves information about the specified heap.HeapReAlloc Reallocates a block of memory from a heap.HeapSetInformation Sets heap information for the specified heap.HeapSize Retrieves the size of a memory block allocated from a heap. HeapUnlock Releases ownership of the lock associated with a specified heap. HeapValidate Attempts to validate a specified heap.HeapWalk Enumerates the memory blocks in a specified heap.Windows堆的数据结构1.前端分配器(Front End Allocator)是对的一个抽象优化层。

Windows系统内存管理技巧

Windows系统内存管理技巧

Windows系统内存管理技巧作为一款广泛使用的操作系统,Windows在内存管理方面拥有许多技巧,可以帮助提升系统的性能和稳定性。

本文将介绍一些Windows系统内存管理的技巧,旨在帮助读者更好地利用系统资源,优化计算体验。

一、了解内存管理基础知识在探索Windows系统内存管理技巧之前,首先需要了解一些基础知识。

内存是计算机中的重要组成部分,用于存储运行中的程序和数据。

Windows系统使用虚拟内存管理技术,将硬盘空间用作内存扩展,以满足程序的需求。

理解内存和虚拟内存的概念,对于更好地管理Windows系统内存至关重要。

二、合理调整虚拟内存设置虚拟内存是一项重要的内存管理技术,可以有效扩展系统内存。

Windows系统中,虚拟内存的大小可以通过调整页面文件的设置进行管理。

默认情况下,系统会自动管理虚拟内存的大小,但用户可以根据自己的需求进行手动设置。

当系统出现内存不足的情况时,可以适当增加虚拟内存的大小来解决问题。

打开“控制面板”-“系统和安全”-“系统”,点击“高级系统设置”,在“性能”选项卡中的“设置”中找到“高级”选项卡,点击“更改”按钮,即可对虚拟内存进行设置。

三、优化内存使用除了调整虚拟内存设置,还可以通过一些优化手段来改善Windows系统的内存使用情况。

以下是一些常用的内存优化技巧:1. 关闭不必要的后台应用程序和进程:在任务管理器中可以查看当前正在运行的应用程序和进程。

关闭不必要的后台应用程序和进程,可以释放一部分内存资源。

2. 优化启动项:在系统启动时,有许多应用程序会自动启动并占用内存。

通过管理启动项,可以禁用一些不必要的自启动程序,提升系统的启动速度并释放内存。

3. 清理垃圾文件:定期清理临时文件、缓存文件和回收站中的垃圾文件,可以释放磁盘空间和一部分内存。

4. 使用高效的软件和浏览器:一些软件和浏览器可能会占用较多的内存资源。

选择使用较为高效的软件和浏览器,可以减少内存的占用。

第7章 Win2000内存管理(2)

第7章  Win2000内存管理(2)

有关虚拟内存管理的性能计数器
性能计数器
Memory:Available Bytes Memory:Committed Bytes Memory:Committed Limit
描述
当前可用的存储空间的大小 提交的私有地址空间数量(一些在 物理内存,一些在页文件中) 不增页文件的大小情况下,可提交 的内存字节数
用户空间内存分配方式

以页面为单位的虚拟内存分配方法
适用于管理大型对象或数据结构,分两个阶段: 保留内存:为线程将来使用所保留的一块虚拟地 址 提交内存:向保留的地址空间提交物理页面 由VirtualAllo和VirtualFree实现。
内存管理API函数

VirtualAlloc:在调用进程的虚拟地址中保留或提
WIN WIN32 WIN WIN32 NT加 应用程 WIN32 应用程 NT加 序 载空 载空 用户进 序 间 间 程空间
DLL(动态 链接库)和 其它共享组 件 低层内存管理、 文件系统、驱动 程序(VxD)程 序
基本 基本 MS基本 MSDOS MSDOS DOS 程序 程序 程序
Байду номын сангаас
64KB
2GB-192KB 0X10000~0X7FFEFFF

虚拟地址空间示例
进程A进驻主存
提交页 (committed) VirtualAllo
A进程的 物理空间
保留页 (reserved) 空闲页 (free)
VirtualFree
系统内存分配



非分页合并内存(Nonpaged PoolSize):包含必 须驻留在内存的内核模式操作的等必须保留在 内存中才能有效工作的占用代码和数据。它们 不能被交换到磁盘上。 分页合并内存(paged PoolSize) :存储迟早需 要的代码和数据内存部分。可交换到磁盘上, 但将其到磁盘上之前,Windows会将交换其他进 程 可在注册表中改变它们的大小 。

Windows CE内存管理(CE5.0&CE6.0)

Windows CE内存管理(CE5.0&CE6.0)

物理地址

虚拟内存模型(2)-CE5.0
FFFF FFFF
Kernel Space
Kernel Addresses: KPAGE, Trap Area, Others Unused
Total 4 GB Virtual Space 2 GB Kernel Space
User Space
Slots 63 – resources dll
Logical Memory (Heap, stack) Virtual Memory Physical Memory * Storage Device
Windows CE采用层次化的结构
内存结构(2)

物理内存


在内部或外部总线上可访问的实际的 RAM/ROM RAM分为对象存储区域(object store)和应 用程序内存区域(program memory)。 ROM中存放的内容可以是压缩的,也可以是 不压缩的(可本地执行--XIP,executed in place)。 Windows CE只能管理512MB的物理内存
WinCE 6的虚拟内存模型(5)
内核空间





低1G:静态虚拟地址 0xC0000000–0xC7FF FFFF: 内核加载的(XIP) DLL 0xC8000000–0xCFFFFFFF:文 件系统的对象存储区 0xD0000000–0xDFFFFFFF:内 核模式的程序执行区。如 GWES.DLL,系统DLL,内核驱 动等。 0xE0000000–0xEFFFFFFF:同 上。除了SH4架构的CPU。 0xF0000000–0xFFFFFFFF:捕 获系统调用,包含核心数据页。
FFFF FFFF
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Windows内存管理机制
在编程中,很多Windows或C++的内存函数不知道有什么区别,更别谈有效使用;根本的原因是,没有清楚的理解操作系统的内存管理机制,本文企图通过简单的总结描述,结合实例来阐明这个机制。

本文目的:
对Windows内存管理机制了解清楚,有效的利用C++内存函数管理和使用内存。

本文内容:
本文一共有六节,由于篇幅较多,故按节发表。

其他章节请看本人博客的Windows内存管理及C++内存分配实例(一)(二)(三)(四)和(五)。

1. 进程地址空间
2.内存状态查询函数
3.内存管理机制--虚拟内存 (VM)
4.内存管理机制--内存映射文件 (Map)
5.内存管理机制--堆 (Heap)
使用场合
操作系统为每个线程都建立一个默认堆栈,大小为1M。

这个堆栈是供函数调用时使用,线程内函数里的各种静态变量都是从这个默认堆栈里分配的。

堆栈结构
默认1M的线程堆栈空间的结构举例如下,其中,基地址为0x0004 0000,刚开始时,CPU的堆栈指针寄存器保存的是栈顶的第一个页面地址
0x0013 F000。

第二页面为保护页面。

这两页是已经分配物理存储器的可用页面。

随着函数的调用,系统将需要更多的页面,假设需要另外5页,则给这5页提交内存,删除原来页面的保护页面属性,最后一页赋予保护页面属性。

当分配倒数第二页0x0004 1000时,系统不再将保护属性赋予它,相反,它会产生堆栈溢出异常STATUS_STACK_OVERFLOW,如果程序没有处理它,则线程将退出。

最后一页始终处于保留状态,也就是说可用堆栈数是没有1M的,之所以不用,是防止线程破坏栈底下面的内存(通过违规访问异常达到目的)。

当程序的函数里分配了临时变量时,编译器把堆栈指针递减相应的页数目,堆栈指针始终都是一个页面的整数倍。

所以,当编译器发现堆栈指针位于保护页面之下时,会插入堆栈检查函数,改变堆栈指针及保护页面。

这样,当程序运行时,就会分配物理内存,而不会出现访问违规。

使用例子
改变堆栈默认大小:
有两个方法,一是在CreateThread()时传一个参数进去改变;
二是通过链接命令:
#pragma comment(linker,"/STACK:102400000,1024000")
第一个值是堆栈的保留空间,第二个值是堆栈开始时提交的物理内存大小。

本文将堆栈改变为100M。

堆栈溢出处理:
如果出现堆栈异常不处理,则导致线程终止;如果你只做了一般处理,内存
结构已经处于破坏状态,因为已经没有保护页面,系统没有办法再抛出堆栈溢
出异常,这样的话,当再次出现溢出时,会出现访问违规操作
STATUS_ACCESS_VIOLATION,这是线程将被系统终止。

解决办法是,恢复
堆栈的保护页面。

请看以下例子:
C++程序如下:
bool handle=true;
static MEMORY_BASIC_INFORMATION mi; LPBYTE lpPage;
//得到堆栈指针寄存器里的值
_asm mov lpPage, esp;
// 得到当前堆栈的一些信息
VirtualQuery(lpPage, &mi, sizeof(mi));
//输出堆栈指针
printf("堆栈指针=%x\n",lpPage);
// 这里是堆栈的提交大小
printf("已用堆栈大小=%d\n",mi.RegionSize); printf("堆栈基址=%x\n",mi.AllocationBase);
for(int i=0;i<2;i++)
{
__try
{
__try
{
__try
{
cout<<"**************************"<<endl;
//如果是这样静态分配导致的堆栈异常,系统默认不
抛出异常,捕获不到
//char a[1024*1024];
//动态分配栈空间,有系统调用Alloca实现,自动
释放
Add(1000);
//系统可以捕获违规访问
int * p=(int*)0xC00000000;
*p=3;
cout<<"执行结束"<<endl;
}
__except(GetExceptionCode()==STATUS_ACCESS_ VIOLATION ? EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH)
{
cout<<"Excpetion 1"<<endl;
}
}
__except(GetExceptionCode()==STATUS_STACK_OVERFL OW ? EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH)
{
cout<<"Exception 2"<<endl;
if(handle)
{
//做堆栈破坏状态恢复
LPBYTE lpPage;
static SYSTEM_INFO si;
static MEMORY_BASIC_INFORMATION mi;
static DWORD dwOldProtect;
// 得到内存属性
GetSystemInfo(&si);
// 得到堆栈指针
_asm mov lpPage, esp;
// 查询堆栈信息
VirtualQuery(lpPage, &mi, sizeof(mi));
printf("坏堆栈指针=%x\n",lpPage);
// 得到堆栈指针对应的下一页基址
lpPage = (LPBYTE)(mi.BaseAddress)-
si.dwPageSize;
printf("已用堆栈大小=%d\n",mi.RegionSize);
printf("坏堆栈基址=%x\n",mi.AllocationBase); //释放准保护页面的下面所有内存
if (!VirtualFree(mi.AllocationBase,
(LPBYTE)lpPage -
(LPBYTE)mi.AllocationBase,
MEM_DECOMMIT))
{
exit(1);
}
// 改页面为保护页面
if (!VirtualProtect(lpPage, si.dwPageSize,
PAGE_GUARD | PAGE_READWRITE, &dwOldProtect))
{
exit(1);
}
}
printf("Exception handler %lX\n", _exception_code()); }
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
cout<<"Default handler"<<endl;
}
}
cout<<"正常执行"<<endl;
//分配空间,耗用堆栈
char c[1024*800];
printf("c[0]=%x\n",c);
printf("c[1024*800]=%x\n",&c[1024*800-1]);
}
void ThreadStack::Add(unsigned long a)
{
//深递归,耗堆栈
char b[1000];
if(a==0)
return;
Add(a-1);
}
程序运行结果如下:
可以看见,在执行递归前,堆栈已被用了800多K,这些是在编译时就静态决定了。

它们不再占用进程空间,因为堆栈占用了默认的1M进程空间。

分配是从栈顶到栈底的顺序。

当第一次递归调用后,系统捕获到了它的溢出异常,然后堆栈指针自动恢复到原来的指针值,并且在异常处理里,更改了保护页面,确保第二次递归调用时不会出现访问违规而退出线程,但是,它仍然会导致堆栈溢出,需要动态的增加堆栈大小,本文没有对这个进行研究,但是试图通过分配另外内存区,改变堆栈指针,但是没有奏效。

注意:在一个线程里,全局变量加上任何一个函数里的临时变量,如果超过堆栈大小,当调用这个函数时,都会出现堆栈溢出,这种溢出系统不会抛出堆栈溢出异常,而直接导致线程退出。

对于函数1调用函数2,而函数n-1又调用函数n的嵌套调用,每层调用不算临时变量将损失240字节,所以默认线程最多有1024*(1024-2)/240=4360次调用。

加上函数本身有变量,这个数目会大大减少。

相关文档
最新文档