Windows内存管理机制
- 格式:doc
- 大小:107.50 KB
- 文档页数:10
windows heapalloc和heapfree 原理
Windows的HeapAlloc和HeapFree是用于在进程的堆中分配和释放内存块的函数。
堆是进程用来存储动态分配的内存的一种数据结构,每个进程都有一个独立的堆。
HeapAlloc函数通过系统调用HeapCreate来创建进程的堆,调用者指定了所需内存块的大小和一些标志。
系统会根据需要从进程空间中的堆中分配出一块足够大的内存,然后把这块内存标记为已分配。
如果堆没有足够的连续内存来满足请求,系统会进行相应的内存管理操作,例如从操作系统申请更多内存。
HeapFree函数用于释放已分配的内存块,调用者需要指定要释放的内存块的地址。
系统会将指定的内存块标记为未分配,然后根据需要进行合并操作,以便将相邻的未分配的内存块合并成一个更大的内存块。
HeapAlloc和HeapFree的实现涉及到底层的内存管理机制,包括虚拟内存管理和物理内存管理。
Windows使用虚拟内存机制来为每个进程提供一种看似连续的地址空间,而实际上这些地址可能对应于不连续的物理内存页。
当HeapAlloc调用时,系统会根据虚拟内存空间的情况来选择一个合适的物理内存页来分配内存。
类似地,当HeapFree调用时,系统会将释放的内存标记为未分配,并可能触发相应的内存管理操作,例如将物理内存页返回给操作系统。
总而言之,Windows的HeapAlloc和HeapFree通过调用底层的内存管理机制来实现动态分配和释放内存的功能,涉及到虚
拟内存管理和物理内存管理等复杂的操作。
这些函数的具体实现细节由操作系统负责,开发者只需要使用它们来申请和释放内存块。
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的虚拟内存
Windows 10 的虚拟内存用久了也会出现一些问题,那么如何管理Windows 10 的虚拟内存的呢?下面是店铺收集整理的如何管理Windows 10 的虚拟内存,希望对大家有帮助~~
管理 Windows 10 的虚拟内存的方法
工具/原料
Windows 10 专业版。
方法/步骤
打开设置窗口。
“开始”-->“设置”。
进入性能调整选项窗口。
在设置窗口里,输入“性能”,然后在窗口筛选出来的列表里,点选“调整 Windows 的外观和性能”。
在弹出的“性能选项”窗口里,点选“高级”选项卡。
在“高级”选项卡中,点击“虚拟内存”里的“更改”。
在接下来的窗口中,查看窗口下方关于当前虚拟内存分配的情况,特别是“推荐”和“当前已分配”这两个值。
如果确定是当前分配值过低导致电脑性能出现问题,可以取消对“自动管理分页文件的大小”选项,然后在“自定义大小”中,输入你要设置的最大和最小值。
其中最小值可以是第5 步骤中的“推荐”值,当然最大值更要比它大了。
重启计算机,上述设置就会生效。
如果重启之后,觉得计算机性能没有提升或甚至出现了倒退,可以按上述步骤,将虚拟内存恢复成让系统自动管理。
如何管理 Windows 10 的虚拟内存。
堆(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系统的内存使用情况。
以下是一些常用的内存优化技巧:1. 关闭不必要的后台应用程序和进程:在任务管理器中可以查看当前正在运行的应用程序和进程。
关闭不必要的后台应用程序和进程,可以释放一部分内存资源。
2. 优化启动项:在系统启动时,有许多应用程序会自动启动并占用内存。
通过管理启动项,可以禁用一些不必要的自启动程序,提升系统的启动速度并释放内存。
3. 清理垃圾文件:定期清理临时文件、缓存文件和回收站中的垃圾文件,可以释放磁盘空间和一部分内存。
4. 使用高效的软件和浏览器:一些软件和浏览器可能会占用较多的内存资源。
选择使用较为高效的软件和浏览器,可以减少内存的占用。
windows的内存管理机制Windows的内存管理机制在计算机系统中,内存管理是一个非常重要的方面,它负责管理计算机系统中的内存资源,确保程序能够正常运行。
Windows作为一种常见的操作系统,也有自己独特的内存管理机制。
一、虚拟内存管理Windows采用了虚拟内存管理机制,将物理内存和虚拟地址空间进行映射,使得每个进程都拥有独立的地址空间。
这样可以提高内存利用率,同时也增加了系统的稳定性和安全性。
Windows的虚拟内存管理机制通过将虚拟地址空间划分为固定大小的页面,将页面映射到物理内存或磁盘上的页面文件。
当程序需要访问某个虚拟地址时,系统会根据页表的映射关系将对应的页面加载到物理内存中,如果物理内存不足,系统会将不常用的页面置换到磁盘上的页面文件中。
二、内存分页Windows将内存分为固定大小的页,一般为4KB。
这样的页大小既能够满足大部分程序的内存需求,又不会造成过多的内存浪费。
内存分页的好处是可以更灵活地管理内存资源。
系统可以按需分配和回收页面,提高内存利用率。
同时,内存分页也增加了内存的安全性,不同的进程之间无法直接访问对方的内存空间,避免了数据的混乱和安全风险。
三、内存保护Windows的内存管理机制还包括内存保护机制,可以确保不同进程之间的内存空间不会相互干扰。
每个进程都有自己的地址空间,内存保护机制可以防止一个进程访问其他进程的内存空间,增强了系统的稳定性和安全性。
四、内存回收Windows的内存管理机制还包括内存回收机制,当一个进程不再需要某个页面时,系统会将该页面回收,释放给其他进程使用。
内存回收可以提高内存的利用率,避免内存的浪费。
五、内存压缩Windows还引入了内存压缩的机制,当系统内存不足时,会将一部分内存压缩,从而释放出更多的内存空间。
内存压缩可以减少对磁盘页面文件的频繁访问,提高系统的响应速度。
六、内存分配Windows的内存管理机制还包括内存分配机制,用于分配和回收内存资源。
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次调用。
加上函数本身有变量,这个数目会大大减少。