Windows内存管理小白入门

122
0
2020年12月9日 13时51分
Z

掌握Windows系统内存管理器的基本概念,并了解其内存管理机制,有如下优点:

  • 拓展软件问题的解决思路
  • 帮助定位软件问题
  • 发现软件中存在的可优化点,并提供优化方向

本文分三个方向对Windows内存管理进行概述。

一、Windows系统架构

 

Windows内存管理小白入门插图

 

首先,我们了解下用户模式和内核模式。

 

1)用户模式
  • 固定的系统支持进程:登录进程winlogon.exe、会话管理器进程Smss.exe等;
  • 服务进程:进程管理器、假脱机服务,一般是系统启动后自动启动,无用户交互界面,后台一直运行;
  • 用户应用程序:windows32位、windows64位;
  • 环境子系统:实现了操作系统环境的部分支持,当今windows系统只有windows子系统,提供win API;
  • 子系统DLL:用户程序通过子系统DLL调用windows系统内部服务。

 

2)内核模式
  • 执行体:Ntoskrnl.exe上层,包含基本的操作系统服务,如内存管理、进程线程管理、安全性、I/O、网络和跨进程通信;
  • 内核: Ntoskrnl.exe下层,由一组低层次的操作系统功能构成,如线程调度,中断和异常分发,以及多处理器同步。为执行体提供服务以实现更高层次的功能;
  • 设备驱动程序: Win32K.sys,既包括硬件设备驱动程序(用户I/O转为设备I/O),也包括软件设备驱动程序(文件系统和网络驱动程序);
  • 硬件抽象层:Hal.dll,把内核、设备驱动程序、windows执行体的其余部分,跟与平台相关的硬件差异隔离开来;
  • 窗口和图形:实现了图形用户界面函数,比如对窗口的处理,用户界面控件,以及绘制等。

然后,我们看下更详细的架构图

 

Windows内存管理小白入门插图(1)

 

其中,NTDLL.DLL负责用户模式与内核模式之间的切换;内存管理器是内核模式下执行体组件之一,实现了一种内存管理方案。

 

二、内存管理中的基本概念

内存管理是利用windows系统执行体组件之一——内存管理器实现的内存管理机制。

我们写代码中经常遇到地址和内存的概念,它们是独立开的。地址只是一个虚拟代号,人为定义的一种管理方式而已,指明数据在什么地方;地址不占用硬件资源。内存是真实存在的物理或虚拟内存,占用硬件资源。_只有为地址绑定了内存,该地址才是有效地址,否则就是野指针。_

 

1.地址基本概念

1)地址空间

地址空间是程序可使用的地址范围(可寻址范围),是应用程序内部的一种管理机制,虚拟的,不是真实存在的。

 

2)地址空间范围

X86 CPU包含32位地址线,可寻址范围$2^{32}$,即4GB;X64 CPU包含64位地址线,可寻址范围$2^{64}$即16EB,受系统和硬件限制,实际只实现了$2^{48}$即256TB。

 

3)地址空间划分

Windows内存管理小白入门插图(2)

 

4)地址区域 #一块连续的地址空间

 

Windows内存管理小白入门插图(3)

 

2.内存基本概念

1)物理内存

系统可以使用的实际内存,CPU可以直接访问的内存,真实存在的。

 

2)虚拟内存

将硬盘文件虚拟成内存使用(C:\pagefile.sys),不是真正的内存。CPU只能访问物理内存,如果要访问虚拟内存数据,必须将虚拟内存数据放到物理内存。

 

3)内存区域

同地址区域,指一块连续的内存。

 

3.虚拟内存机制

当用户程序所需的内存超过当前系统可提供的物理内存时,系统会把一部分数据和代码转移到磁盘上,由磁盘文件充当内存,当需要访问这一部分数据或执行某些代码时,再由系统将其转移到物理内存,供CPU访问和执行。

将硬盘文件虚拟成内存使用(C:\pagefile.sys)。

CPU只能访问物理内存,如果要访问虚拟内存数据,必须将虚拟内存数据放到物理内存。

 

1)从内存获取数据的过程

 

Windows内存管理小白入门插图(4)

 

数据在物理内存还是虚拟内存中,没有规律,只取决于数据使用的频繁程度。

 

2)页面交换机制

虚拟内存与物理内存进行数据交换。当线程访问某个地址指向的数据时,如果数据在虚拟内存中,系统会把该地址附近(一页)的数据一同交换到物理内存,以此优化内存的使用效率和执行效率。

 

3)地址转译机制

Windows内存管理小白入门插图(5)

 

4.内存分配

 

Windows内存管理小白入门插图(6)

 

关于内存分配这块,我们重点来了解下内存映射文件。它将文件映射成内存,即把硬盘上的文件当内存来用,当用户读写文件映射得到的内存时,就是在读写文件。常用于进程间通信。其主要步骤如下:

 

  • 创建或打开硬盘文件
  • 创建内存映射文件
  • 加载内存映射文件
  • 使用内存
  • 卸载内存映射文件
  • 关闭内存映射文件
  • 关闭文件

 

Windows内存管理小白入门插图(7)

 


最后,我们做个总结:

 

1.new/malloc 只分配小块内存,有时会有内存空洞

new/malloc在堆上分配内存,分配的内存都是连续的,如图所示,假设分配了两块大小为500M的大内存,两次分配的内存间一般都会有空闲内存,这块内存很有可能因为用户申请大小不合适导致永远不会被使用,即“内存空洞”。

2.大块内存分配和大型结构数组考虑用VirtualAlloc

3.大文件读写考虑用内存映射文件

发表评论

后才能评论