GlobalAlloc 和 GlobalFree 函数在 kernel32.dll 库中定义。通过使用 DllImport 属性,可从我的 C# 压力器程序调用它们。GlobalFree 的原始 C++ 签名是:
HGLOBAL GlobalAlloc(UINT uFlags,
SIZE_T dwBytes);
返回类型 HGLOBAL 是众多 Win32 符号常量之一。它实际上是指向 GlobalAlloc 分配的第一个内存地址的指针,因此,我将该类型转换为 System.IntPtr 类型。IntPtr 是一个特定于平台的类型,用于表示指针或句柄。我将在下一节中更全面地解释 GlobalAlloc 及其搭档 GlobalFree。我使用 GlobalMemoryStatus 函数检索当前可用的内存量,这样,我就可以确定使用 GlobalAlloc 函数尝试分配多少内存了。GlobalMemoryStatus 的 Win32 签名是:
void GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer);
将一个指向结构的指针/引用传递给 GlobalMemoryStatus,然后 GlobalMemoryStatus 使用内存信息填充该结构。该结构在图 2 中定义。该结构中最重要的字段是 dwAvailVirtual 字段,调用 GlobalMemoryStatus 函数之后,该字段将保留可用虚拟内存的字节量。
EatMem 工具基本上是一个有组织的 while 循环 - 它将进行迭代,直到当前系统日期/时间超出规定的日期/时间:通过将在命令行中指定的持续时间(以分为单位)加上该工具启动时的时间,确定该这一日期/时间。在主 while 循环内,有一个执行了 8 次的次循环。该次循环在功能上不是必需的;它能够较好地偶尔显示进度输出。
工具的详细介绍
现在,我们详细介绍一下 EatMem 工具的每个部分。我将在本专栏的下一节中讨论神奇的控制台输出,之后我将讨论针对基本代码的替代方案和一些修改。图 3 显示将运行 EatMem 的代码。
Figure 3 Initialize EatMem
const uint basicUnit = 1024; // 1 KB
Random r = new Random();
if (args.Length != 1 || !args[0].StartsWith("-d"))
{
Console.WriteLine("\nExample usage: eatmem -d100");
Console.Write("Randomly eats between 10% and 70%
Console.WriteLine(" of virtual memory for 100 minutes");
}
// determine stopping time
int duration = int.Parse(args[0].Substring(2, args[0].Length-2));
TimeSpan ts = new TimeSpan(0, duration, 0); // hr, min, sec
DateTime startTime = DateTime.UtcNow;
DateTime stopTime = startTime + ts;
我首先声明一个常量 1024,因为我将以千字节进行所有的 EatMem 显示,同时这些计算将以字节执行。接下来实例化一个 Random 对象,这样我之后就可以生成伪随机数。
然后,我使用一项非常原始的技术获取 EatMem 应该运行的持续时间(以分为单位)。我的代码假设有一个命令行参数,它的确切形式是 -dN,其中 N 是数字。我将获取显示的数字,因为 args[0] 将表示诸如"-d123"的字符串,而 Substring(2) 将是"123"部分。我使用一项标准的技术来确定停止时间:我创建一个 TimeSpan 对象指示所需的分钟数,然后使用该 TimeSpan,其中重载的"+"操作符在 EatMem 启动时将应用到该时间。
在进入主 while 控制循环之前,我要做的最后一件事是显示该输出的简要标头以及以下几行代码:
// print output headers
WriteLine("Begin EatMem for " + duration + " minutes");
WriteLine("Consuming random 10%-70% of virtual memory");
WriteLine("Launch test harness while EatMem stressor runs");
WriteLine(" Available Available Current");
WriteLine(" Physical Virtual Memory");
WriteLine(" Time Memory Memory Allocation Pct.");
WriteLine("---------------------------------------------");
请注意,为简明起见,我稍微改动了实际语句。您可以在本专栏附带的代码下载中获取确切的语句。