《windows系统编程》——内存基础与相关结构
《Windows系统编程》——内存基础与相关结构 笔记
课堂笔记
WINAPI学习
在这堂课也有点摸清楚一些规律了,WINAPI 中的一些结构体,除了定义结构体本身以外还会定义它的指针类型,一般在该变量类型名前加上前缀 lp(LP)。
GetSystemInfo
GetSystemInfo 函数用于获取系统信息,传入参数位 SYSTEM_INFO *,没有返回值,获取的系统信息通过 SYSTEM_INFO 结构体返回,结构体定义如下。
1 | typedef struct _SYSTEM_INFO { |
其中
- dwPageSize 为内存页大小
- lpMinimumApplicationAddress 为进程可用的最小内存地址
- lpMaximumApplicationAddress 为进程可用的最大内存地址
…
我们可以通过调试手段方便地查看结构体各个成员
MemoryStatusEx
MemoryStatusEx 函数用于获取当前电脑内存信息。传入参数类型为 LPMEMORYSTATUSEX,也就是 MEMORYSTATUSEX * 类型。这个类型的结构体定义如下:
1 | typedef struct _MEMORYSTATUSEX { |
除了 dwLength 外,第一个参数就是 dwMemoryLoad,它告诉了我们当前物理内存占用情况,也就是我们任务管理器看到的内存占用百分比,写一个程序输出就会发现它与任务管理器上显示的信息一致。
1 |
|
运行结果:
剩下的成员
- ullTotalPhys:实际物理内存量
- ullAvailPhys:可使用的物理内存量
- ullTotalPageFile:当前系统已提交的内存限制
- ullAvailPageFile:当前系统可以提交的最大内存量
- ullTotalVirtual:调用进程的虚拟空间的用户内存大小
- ullAvailVirtual:当前用户空间没有提交的内存
- ullAvailExtendedVirtual:保留,始终为0
还是用以上的方式去获取结构信息,调试查看结构体成员。
GetProcessMemoryInfo
用于获取进程的一个内存信息,用到这个 api 需要包含 Psapi.h。第一个参数为 HANDLE 类型,也就是我们获取的进程的句柄,第二个参数是一个结构体,用于接收返回的信息,第三个参数是该结构体的大小。
- PeakWorkingSetSize 是该进程创建以来使用的内存大小(peak表示顶峰)。
- WorkingSetSize 是该进程当前使用的内存大小。
那么我们获取当前进程所使用的内存信息就像下面一样获取。
1 | PROCESS_MEMORY_COUNTERS psmemCounters; |
VirtualAlloc
用于为本进程分配内存。第一个参数为分配内存的地址,填 NULL 表示让操作系统自己分配,第二个参数就是我们要分配的内存的大小,第三个参数是内存的属性,一般我们传入 MEM_COMMIT 即可,它的作用是为指定的保留内存页面分配内存费用(来自内存的总大小和磁盘上的页面文件)该函数还保证当调用者稍后最初访问内存时,内容将为零,除非/直到实际访问虚拟地址,否则不会分配实际的物理页面,第四个参数是内存的保护属性,就是读写执行那些的,实际上它有以下那么多属性
返回值为一个地址指针。
VirtualFree
用于为本进程释放内存,第一个参数为释放内存的起始地址,第二个参数为 size,但是通常情况下我们只有传 0 才能成功释放,传其他值不能够释放。第三个参数我们就给 MEM_REALEASE,表示释放这个内存。
其实释放这个内存的函数,两个参数都是固定的。
关于这个参数的解释可以去看 msdn,有详细说明。
VirtualQuery
查询内存页面的属性,第一个参数为内存地址,第二个参数为接受内存信息的结构体指针,第三个参数为结构体大小。
结构体定义如下
1 | typedef struct _MEMORY_BASIC_INFORMATION { |
- BaseAddress:内存基地址
- AllocationBase:申请区域的基地址
- AllocationProtect:内存保护属性,读写执行那些的
- RegionSize:区域的大小
- State:页面的状态
- Protect:区域中页面的访问保护
- Type:页面类型
VirtualProtect
更改内存页保护属性,第一个参数为该内存页地址,第二个参数为大小,第三个参数为要设置的保护属性,第四个参数用于接收该内存页原属性。
总结
以上 Virtual 开头的 api 均有 Ex 模式, Ex 模式表示在别的线程当中进行对应的操作。不过事先我们要先获取进程句柄,并且 给上 PROCESS_ALL_ACCESS 的权限。
这节课也就是学习了一些内存相关 API 的使用,算打点基础吧,本节课写的代码:
1 |
|