Windows:内存管理机制

内存对齐

为什么要对齐:

  1)平台移植性:

    某些平台读取内存是以2kb,4kb为单位的。有些平台不支持任意地址的访问。

  2)高效性,数据结构,应该尽可能在自然边界上对齐,未对齐访问会多几次访问。

主要跟硬件设计有关。

 

内存对齐的规则:

struct node{
    char a;
    int b;
    short c;
}

 

默认对齐系数:一般为4

对齐大小:为当前变量和默认对齐系数中最小的那个决定。比如char a的对齐大小为1,int b的对齐大小为4, short c的对齐大小为2.

1)结构体变量的起始地址能够被最宽的成员变量整除。(一般是满足的,不需要特别计算)

2)结构体中每个成员的对齐大小与起始地址的差要为对齐大小的整数倍,否则在前一个变量后补全。

  对于int b来说,只有char a后面补上3,那么与起始地址的差为8,才能是4的整数倍。

3)结构体的总大小要是最宽变量的大小的整数倍,否则在最后补全,只有short c后补2个字节才能满足这个规则。

 

 

windows分配内存机制

操作系统将物理内存映射成进程的虚拟内存,并提供API(VirtualAlloc、VirtualFree)对虚拟内存进行管理。在virtual memory API的基础上又提供了Heap Memory API(HeapAlloc),C语言的malloc和free就是建立在这个基础上的。

使用virtual alloc分配的内存都是4KB的整数倍。

 

 

进程的虚拟地址及页

每个进程的内存都是独立的,虚拟的,进程间互不干扰的。每个进程在自己的线性的虚拟地址下跑程序。

32位虚拟内存大小为4G. 但是程序并不能访问所有4G内存,只能访问其中的2G(最高和最低的64byte也不能访问)

进程的虚拟地址最后要转换为实际的物理地址。虚拟地址到物理地址的转换是通过页表完成的。

页目录的组成(每个进程都有自己独立的页目录):

  在Intel x86 CPU中页表目录的指针存在CR3寄存器中,该寄存器指向一个1024位的数组,数组元素是32位的,

  数组元素表示的是物理内存的基地址,还有状态位表明内存是否被使用。

 

DLL程序没有自己的“私有”的空间。它们总是被映射到其他应用程序的地址空间中,当做其他应用程序的一部分运行。原因很简单,如果它不和其他程序同属一个地址空间,应用程序就不能调用它。

 

进程中地址布局

 

1. 栈区,位于地址的顶部,增长方式是从大到小

2. 堆区,位于地址的尾部+代码段offset+全局数据段offset,增长方式是从小到大

 

进程中内存的分配

1. 起始地址:一般是64k的整数倍

2. 空间大小:系统页面大小的整数倍(x86/x64下是4KB)

虚拟内存的实现和页交换文件

 

 

我们可以调用函数从地址空间中预定一块内存,在实际使用的时候再从物理内存中调拨,相当于C语言中的声明与定义,当不再需要内存的时候可以还给系统,先将一块内存标记为可用的(标记线性空间中的地址空闲可用),当积攒够了一定的空闲内存是在取消提交(把物理内存归还给操作系统)。

对于物理内存而言,在暂时不用或者内存紧张的情况下可以被交换到磁盘上的页交换文件中,在需要的时候(CPU缺页中断)再从也交换文件中载入到内存中,这样就提高了内存的使用效率。

页交换文件的使用当然需要一定的代价,频繁的在磁盘与内存将交换页会导致系统性能下降(硬盘颠簸),一般而言采用增加内存的办法比提升CPU对系统的性能改善更大。

 

posted @ 2021-05-25 20:14  Dylan_Liang  阅读(737)  评论(0编辑  收藏  举报