zoukankan      html  css  js  c++  java
  • 内存管理[1]

    Windows 是多任务的操作系统, 一个任务就是一个应用(应用程序)、一个应用占一个进程; 在一个进程里面, 又可以运行多个线程(所以就有了很多"多线程编程"的话题).

    对 Win32 来讲, 系统给每个进程 4GB 的地址空间:
    低端 2GB($00000000 - $7FFFFFFF) 给用户支配;
    高端 2GB($80000000 - $FFFFFFFF) 留给系统使用.

    文件或程序要调入内存才能工作, 先看看我们的内存到底有多大吧.

    在系统盘根目录下有个 pagefile.sys 文件, 这就是我们的 "虚拟内存"(虚拟内存是以文件的形式存在的).

    把 pagefile.sys 叫做 "虚拟内存" 似乎不妥, 所谓的 "虚拟" 只是相对真实的物理内存(RAM)来讲的; 很多书上的 "物理内存" 指的其实是: RAM + 虚拟内存, 也就是所有可用内存.

    "虚拟内存" 在有些书上也被称作 "页文件" 、"页面文件" 或 "交换文件". "虚拟内存" 的大小可以从 "控制面板" 里设置, 默认是由系统自动管理的.

    使用 "虚拟内存" 是系统的机制, 不管 RAM 有多大, 也应该使用 "虚拟内存".

    RAM 大了, 系统就会少用 "虚拟内存", 从而提高速度; 但 RAM 也不是越大越好, 如果你真的放 4G 的内存条, 系统能够识别并使用的也就是 3G 左右, 因为 Win32 只有 4G 的管理能力(寻址能力), 当然这在 Win64 下要另当别论.

    所谓系统给每个程序 4G, 是给 4G 的 "虚拟的地址表", 绝不是真实的内存, 不然一个记事本、一个计算器就得需要 8G.

    这个 "虚拟的地址表" 在有些书上叫 "虚地址表"、"页映射表" 或 "虚内存地址", 也有叫 "虚拟内存地址", 很容易和 "虚拟内存" 的概念混淆.

    这个 "虚拟的地址表" 上有 4G 个(4294967296 个)地址(0 - $FFFFFFFF), 虽然每个程序都有这样一个表, 但它们并不会冲突, 就因为这些地址是虚拟的, 系统在需要的时候会把它们映射成具体的真实内存的地址. 这样就阻断了一个进程对另一个进程的访问.

    在 Win2000 以前的版本中, 用 GlobalAlloc 申请公用内存, 用 LocalAlloc 申请私有内存; 现在通过 "虚拟的地址表" 使用内存, 在进程中申请的内存都是私有的, 现在的 GlobalAlloc、LocalAlloc 没有区别, 都是执行同样的代码.

    如果需要跨进程的公用内存空间, 需要用 "内存映射" 等手段, 这需要再专题学习.

    总结概念: 物理内存、虚拟内存、虚地址表.
    函数 GlobalMemoryStatus 可以获取它们的信息, 获取后放在 TMemoryStatus 结构中.
    //TMemoryStatus 是 _MEMORYSTATUS 的重命名:
    _MEMORYSTATUS = record
      dwLength: DWORD;        {结构长度}
      dwMemoryLoad: DWORD;    {表示已使用的内存比例的一个整数}
      dwTotalPhys: DWORD;     {物理内存总数}
      dwAvailPhys: DWORD;     {可用物理内存总数}
      dwTotalPageFile: DWORD; {虚拟内存总数}
      dwAvailPageFile: DWORD; {可用虚拟内存总数}
      dwTotalVirtual: DWORD;  {虚地址表中的地址总数}
      dwAvailVirtual: DWORD;  {虚地址表中可用的地址总数}
    end;

    做个小程序看看内存情况:
    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
    
    type
      TForm1 = class(TForm)
        Memo1: TMemo;
        procedure FormCreate(Sender: TObject);
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.FormCreate(Sender: TObject);
    var
      m: TMemoryStatus;
    const
      num = 1024 * 1024;
    begin
      GlobalMemoryStatus(m);
      Memo1.Clear;
      with Memo1.Lines do begin
        Add(Format('dwLength:'        + #9 + '%d', [m.dwLength]));
        Add(Format('dwMemoryLoad:'    + #9 + '%d', [m.dwMemoryLoad]));
        Add(Format('dwTotalPhys:'     + #9 + '%d', [m.dwTotalPhys div num]));
        Add(Format('dwAvailPhys:'     + #9 + '%d', [m.dwAvailPhys div num]));
        Add(Format('dwTotalPageFile:' + #9 + '%d', [m.dwTotalPageFile div num]));
        Add(Format('dwAvailPageFile:' + #9 + '%d', [m.dwAvailPageFile div num]));
        Add(Format('dwTotalVirtual:'  + #9 + '%d', [m.dwTotalVirtual div num]));
        Add(Format('dwAvailVirtual:'  + #9 + '%d', [m.dwAvailVirtual div num]));
      end;
    end;
    
    end.

    我这里的运行效果图:

  • 相关阅读:
    LeetCode120 Triangle
    LeetCode119 Pascal's Triangle II
    LeetCode118 Pascal's Triangle
    LeetCode115 Distinct Subsequences
    LeetCode114 Flatten Binary Tree to Linked List
    LeetCode113 Path Sum II
    LeetCode112 Path Sum
    LeetCode111 Minimum Depth of Binary Tree
    Windows下搭建PHP开发环境-WEB服务器
    如何发布可用于azure的镜像文件
  • 原文地址:https://www.cnblogs.com/wanqian/p/3129338.html
Copyright © 2011-2022 走看看