I'm trying to determine the total amount of physical RAM in the system and
report it for a user. I use the following approach:
MEMORYSTATUSEX msx;
msx.dwLength = sizeof (msx);
if(GlobalMemoryStatusEx(&msx))
{
CString strSz;
unsigned __int64 ulDiv = 1024 * 1024 * 1024; //Or should it be: 1000 *
1000 * 1000
double fV = (double)msx.ullTotalPhys / ulDiv;
strSz.Format(_T("%.2f GB"), fV);
}
It seems to work in Windows XP, but in Vista and Windows 7 I get the
following discrepancies:
RAM reported in msx.ullTotalPhys = 4252442624 bytes
RAM resulting in strSz = "3.96 GB"
RAM reported in the properties for My Computer = "Memory (RAM): 4.00 GB"
I understand that the difference is not that much, but still, where does
that 0.04 GB go? Or should I divide it by 1000 instead of 1024 increments?
FYI. I'm running this test from a program that does not have admin
privileges. Maybe that is why the result is off?
You can use 1000 if you mean GB (gigabytes) or 1024 if you mean GiB
(gibibytes). You should however in this case use 1024.
It's kind of annoying when you don't really know which one to use.
For example with a 2 TB HDD, the manufacturer uses 1000 when they say "2
TB". You might notice that you only have 1.953 "TB" in Windows, but 1024
is used here instead and it still says "TB".
I am a little curious now as well why it shows less for you, since it
seems to work fine here.
I wrote the code from scratch though:
----------------------------------------
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof(memStatus);
if (GlobalMemoryStatusEx(&memStatus))
{
long double totalPhysGiB = memStatus.ullTotalPhys / pow(2.0, 30.0);
long double totalPhysGB = memStatus.ullTotalPhys / pow(10.0, 9.0);
_tprintf(
_T("Total physical memory:\n")
_T("%.2f: GiB\n")
_T("%.2f: GB\n"),
totalPhysGiB,
totalPhysGB);
}
----------------------------------------
Output:
----------------------------------------
Total physical memory:
4.00: GiB
4.29: GB
----------------------------------------
MEMORYSTATUSEX memStatus;
memStatus.dwLength = sizeof(memStatus);
if (GlobalMemoryStatusEx(&memStatus))
{
long double totalPhysGiB = memStatus.ullTotalPhys / pow(2.0, 30.0);
long double totalPhysGB = memStatus.ullTotalPhys / pow(10.0, 9.0);
_tprintf(
_T("Total physical memory:\n")
_T("%I64d: Bytes\n")
_T("%.2f: GiB\n")
_T("%.2f: GB\n"),
memStatus.ullTotalPhys,
totalPhysGiB,
totalPhysGB);
}
The output:
=======================
WINDOWS XP
Total physical memory:
2683285504: Bytes
2.50: GiB
2.68: GB
In My Computer:
2.50 GB of RAM <---- CORREST!
=======================
WINDOWS VISTA
Total physical memory:
4252442624: Bytes
3.96: GiB
4.25: GB
In My Computer:
Memory (RAM): 4.00 GB <--- DOESN'T MATCH!!!
=======================
Windows 7 has the same problem.
Are they rounding it up, or what???? Maybe they use a different API there?
Also, on the side note -- I don't think there's any difference between
'long' and 'long double', is there? At least I can't see any in the 32-bit
machine code in my MS Visual Studio 2002.
Hmm. I am not competent enough to give a good answer that but I think
that's a bit strange. You can also get the same value you see in "My
Computer" via WMI. I have done this in C# but I need to have a look on
how to do it in C++.
Here's a WMI reference:
http://msdn.microsoft.com/en-us/library/aa394572(VS.85).aspx
WMI Classes > Win32 Classes > Computer System Hardware Classes >
Win32_PhysicalMemory Class
Capacity: "Total capacity of the physical memory�in bytes"
Seems like you need to get Capacity from Win32_PhysicalMemory.
>
> Also, on the side note -- I don't think there's any difference between
> 'long' and 'long double', is there? At least I can't see any in the 32-bit
> machine code in my MS Visual Studio 2002.
>
>
"double" is not the same as "long". "double" is a 64-bit floating-point
type while "long" is a 32-bit integral type.
I had a look here just now.. It is Microsoft-specific:
http://msdn.microsoft.com/en-us/library/cc953fe1(VS.80).aspx
Says "Type long double is a floating type that is equal to type double".
I think you should just use "double" instead.
Somehow I must have imagined that I got a warning while using "double"
instead of "long double".
I followed the steps in this article (Getting WMI Data from the Local
Computer):
http://msdn.microsoft.com/en-us/library/aa390423(v=VS.85).aspx
I added my previous code to display the information (unfortunately not
your changes) and this is the output:
----------------------------------------
Total physical memory:
4.00: GiB
4.29: GB
----------------------------------------
If that doesn't work, I really have no idea how to solve that problem
with my level of knowledge. I don't like the idea of rounding the number
because I would assume that the value *should* be exact from the beginning.
Forgot to mention that I have left out error-checking by intention to
make it easier to see what's going on.
(1) If linked like that the code doesn't run on Windows 2000 Pro. (I can
probably fix it by using LoadLibrary and GetProcAddress)
(2) Even though the amount of RAM is reported correct on my previous test
machines, one Windows XP produced very interesting results. The machine has
4GB of RAM installed in it. It has a 32-bit version of XP with SP3 and if I
check it in My Computer properties it is reported as 3GB of RAM. But if I
run your updated program (with WMI Data) it is reported as 4Gib there.
GlobalMemoryStatusEx() returns it as 3GB as well. Have you ever encountered
anything like that?
As I said in my post above, I encountered an issue with your sample not
running on Win2K (not a big deal for many people, but it's easily fixable).
If you attempt to run it as-it-is you'd get an error, saying that "The
ordinal 435 could not be located in the dynamic link library OLEAUT32.dll".
Luckily it has nothing to do with the WMI interfaces used. The ordinal 435
is a call to VarUI8FromStr(). Thus it would be wise to replace it with calls
available through the C run time:
//Where you're converting from VARIANT into UINT64
UINT64 capacity;
_bstr_t bs(val.bstrVal);
if(_stscanf(bs, _T("%I64d"), &capacity) == 1)
totalPhys += capacity;
On the sidenote, I was not able to retrieve the value from 'val' of the type
VARIANT in a 64-bit integer directly without first getting it as a string,
but that is OK. The overhead that it's causing is minuscule.
Thanks again!
From memory, 32 Bit Windows only sees 3GB maximum, anything over is ignored.
Not true of 64 Bit Windows.
hth
Those should be GiB. Anyway, is this on the same computer? I ask because
some computers actually use normal system RAM for graphics.
Uli
No, all the data comes from different computers. But I agree, the ones that
report less memory are 64-bit OS's (at least in my example).
Yes, I agree, but why does WMI function from the sample above return 4GB for
the same machine?
Yeah, I guess you you don't *have* to use VarUI8FromStr. I saw some
other examples where they just did it similarly to how you worked around
it.
> (2) Even though the amount of RAM is reported correct on my previous test
> machines, one Windows XP produced very interesting results. The machine has
> 4GB of RAM installed in it. It has a 32-bit version of XP with SP3 and if I
> check it in My Computer properties it is reported as 3GB of RAM. But if I
> run your updated program (with WMI Data) it is reported as 4Gib there.
> GlobalMemoryStatusEx() returns it as 3GB as well. Have you ever encountered
> anything like that?
Interesting. So it knows 4 GiB is installed but not that only 3 GiB is
available. Then I wonder exactly how that value is retrieved in
Windows... If I can somehow debug it and see how it gets that value... Hmm.
Regarding my code... I noticed "while (returned > 0);" in there. I
forgot to remove it after changing the loop from "do" to "while".
TotalVisibleMemorySize from Win32_OperatingSystem:
http://msdn.microsoft.com/en-us/library/aa394239(v=VS.85).aspx
"Total amount, in kilobytes, of physical memory available to the
operating system. This value does not necessarily indicate the true
amount of physical memory, but what is reported to the operating system
as available to it."
I used pretty much the same code and it works at least.
Output:
----------------------------------------
Total visible memory:
4.00: GiB
4.19: GB
----------------------------------------
On my (64-bit) system, it is just slightly less than 4 GiB (4094.06 MiB).
Yes, it is interesting and I actually like this result :)
> If I can somehow debug it and see how it gets that value... Hmm.
>
Just curious, how do you debug it? Do you use something like SoftICE?
> Regarding my code... I noticed "while (returned > 0);" in there. I forgot
> to remove it after changing the loop from "do" to "while".
Yeah, I noticed it. I learned something too. For instance, the following is
a valid and complilable construct in MS VC++:
a.. while (enumClassObj)
a.. {
a.. //....
a.. }
a.. while (returned > 0);
Both while's aren't actually necessary, by the way. The first one should've
been the 'if' to check if enumClassObj is not NULL. Then it can be an
infinite loop, like while(1) and the way you get out of it is when retuned
== 0, right?
Hah, I just tried to alter your code with the Win32_OperatingSystem class
and it gave a totally ridiculous result on my test Windows XP SP3 machine
(32-bit):
It gave out 2,620,396 bytes! The amount should be 4GiB.
I did the following changes:
1. Line 33, the SQL string becomes "SELECT * FROM Win32_OperatingSystem"
I used * just in case.
2. Line 50, the select statement becomes:
hr = classObj->Get(L"TotalVisibleMemorySize", 0, &val, NULL, 0);
The rest stays the same. Right?
OK. I admit my mistake. I should've read the description better. That value
of 2,620,396 is in KB's and that is closer to the truth, although again,
even if it matches on my XP machine that method returns 3.96Gib and 4.15GB
on the 64-bit Vista with 4.00 GB reported by Windows. They must be rounding
it up. There's no other way?
That's great. Not sure if you checked out my latest code but at least
you have something to choose from.
> Just curious, how do you debug it? Do you use something like SoftICE?
I wanted to use OllyDbg but I realized that when you open "My Computer"
(or similar) in Windows 7, a new process starts and then closes. Some
"dllhost.exe". Maybe injects something into explorer.exe (wild guess
here)? Would have imagined that the process would stick, so I am not
sure if it's handled by explorer.exe entirely or what. Because of this,
I realized it wasn't going to be super easy, so I didn't bother thinking
more about it.
On a 32-bit system at least, I guess one could use Syser which aims to
be a SoftICE replacement. 64-bit.. I am not really sure. WinDbg, maybe?
Never really got around to use it. Not sure if IDA also works as a
kernel debugger.
> Yeah, I noticed it. I learned something too. For instance, the following is
> a valid and complilable construct in MS VC++:
>
> a.. while (enumClassObj)
> a.. {
> a.. //....
> a.. }
> a.. while (returned> 0);
>
>
> Both while's aren't actually necessary, by the way. The first one should've
> been the 'if' to check if enumClassObj is not NULL. Then it can be an
> infinite loop, like while(1) and the way you get out of it is when retuned
> == 0, right?
"while (returned> 0);" does nothing while (returned > 0).
I also realized that enumClassObj remained unchanged but I saw that they
used a while loop in an example code on MSDN, so I just did the same.
IEnumWbemClassObject* pEnumerator = NULL;
...
while (pEnumerator)
...
http://msdn.microsoft.com/en-us/library/aa390423(v=VS.85).aspx
After looking a bit more at their example, it seems like you should call
enumClassObj->Release() in the end as well which I didn't do.
Their example checks for errors as well.
Interesting. Maybe it's showing less because some of the memory is
reserved for the OS or something. If you can somehow know how much is
reserved, maybe you could sum those two values? I am interested in the
answer myself. If you wish, you could try to find out whether it is
likely and how to get that value. I need to get some sleep right now at
least. :)
No, what is the link to it?
> I wanted to use OllyDbg but I realized that when you open "My Computer"
> (or similar) in Windows 7, a new process starts and then closes. Some
> "dllhost.exe". Maybe injects something into explorer.exe (wild guess
> here)? Would have imagined that the process would stick, so I am not sure
> if it's handled by explorer.exe entirely or what. Because of this, I
> realized it wasn't going to be super easy, so I didn't bother thinking
> more about it.
>
Yeah, I looked into this Windows 7 64-bit version I just got and it is quite
difficult to tap into. I was actually more concerned with the Registry and
even there all the data seems to be scrambled (although in some easy manner)
but it is not what it used to be even in XP. Plus, the amounts of memory
available for Windows and the speed with which the code can be executed and
written makes it very difficult to use a debugger on. I'm not sure if most
of that Windows 7 stuff is well documented anyway?
> I also realized that enumClassObj remained unchanged but I saw that they
> used a while loop in an example code on MSDN, so I just did the same.
>
> IEnumWbemClassObject* pEnumerator = NULL;
> ...
> while (pEnumerator)
> ...
This 'while' serves as both an 'if' in case pEnumerator is NULL and an
infinite loop, which is actually a clever design. I didn't catch it
initially, so I should give it to that guy at MS who wrote it :)
> After looking a bit more at their example, it seems like you should call
> enumClassObj->Release() in the end as well which I didn't do.
>
Yeah, I forgot to mention. I caught it too. (I never run someone's code
without rewriting it. :)
:) Yeah, I scoured all over the MSDN and the web as well and can't find any
explanation as to where that memory might be going to. The strange thing is
that I agree that such can be true with my Dell laptop (and Vista 64) that
has a crappy video card and probably uses some of the system RAM. But the
second machine is a desktop with Windows 7 64-bit, and a graphics card with
dedicated 1GB of its own RAM, so there's clearly no need for that machine to
use up any of the system RAM. IMHO, this is something new OS's do when the
amount of RAM is right-on-the-nose, so to speak. (That's pretty much how
they sell those new HDD's. Mine has 1.5 TB on the cover and Windows shows
1.36 TB.) I have no proof of it though. I wish I was better at debugging. I
used to do it with SoftICE (while it still existed) but now it's a
completely different ballgame with a 64-bit architecture.
> Yeah, I noticed it. I learned something too. For instance, the following is
> a valid and complilable construct in MS VC++:
>
> a.. while (enumClassObj)
> a.. {
> a.. //....
> a.. }
> a.. while (returned > 0);
It's legal under any compiler. However, if returned is greater than
zero, it will spin forever. The formatting is confusing you. It's
equivalent to:
while (enumClassObj) { /*statements*/ }
while(returned > 0) /*no statement here*/ ;
So the last 'while' repeats nothing at all.
DS
I meant more like a small part of memory that the OS is using for itself
that can't be used for anything else no matter what.
> (That's pretty much how they sell those new HDD's. Mine has 1.5 TB on the cover and Windows shows
> 1.36 TB.) I have no proof of it though.
HDD space is measured in base 10, meaning kilo is 1000 instead of 1024.
It can cause quite some confusion for people when it's calculated
differently here and there. That's why I say KiB (kibibytes - kilo
binary bytes) like others also are doing, but I am not sure if it is a
standard (it was not at the time I learned about it, I think). So if the
label says 1.5 TB, let's try this:
1.5 / (2^40 / 10^12) = 1.364 TiB
And that's the same number you gave. :)
My laptop HDD is 200 GB. Looking in Windows, it says 186.31 GB.
Let's try this:
186.31 * (2^30 / 10^9) = 200.0488 GB
I wish I was better at debugging. I
> used to do it with SoftICE (while it still existed) but now it's a
> completely different ballgame with a 64-bit architecture.
>
Yeah. I just use OllyDbg now, and a plugin which allows debugging 64-bit
applications. I also have another plugin which changes the disassembler
engine in case I need it. It's only a user-land debugger though. Plugins
are FullDisasm and Olly Advanced.
FullDisasm: http://www.beaengine.org/ - I have useed of some of these
libraries, by the way.
I usually get other plugins from OpenRCE:
http://www.openrce.org/downloads/details/241/Olly_Advanced
It was in an earlier reply I made.
Just a few changes like in the pow() function (because it was measured
in KiB instead of bytes). The rest was mostly the same changes in
variable names and the WQL query.
http://pastebin.com/hjDYhaKD
> Yeah, I looked into this Windows 7 64-bit version I just got and it is quite
> difficult to tap into. I was actually more concerned with the Registry and
> even there all the data seems to be scrambled (although in some easy manner)
> but it is not what it used to be even in XP. Plus, the amounts of memory
> available for Windows and the speed with which the code can be executed and
> written makes it very difficult to use a debugger on. I'm not sure if most
> of that Windows 7 stuff is well documented anyway?
>
Not sure what you mean with the registry. And if you mean the system
would run slower when you have a kernel debugger running, that's
understandable. You should only use it when needed.
I am only taking a guess here by saying Windows 7's internals probably
would not be documented much in detail, other than general things like
how processes work, security, etc.
> This 'while' serves as both an 'if' in case pEnumerator is NULL and an
> infinite loop, which is actually a clever design. I didn't catch it
> initially, so I should give it to that guy at MS who wrote it :)
Seems logical. I just saw it and used it without looking more into it as
it is not production code anyways.
> Yeah, I forgot to mention. I caught it too. (I never run someone's code
> without rewriting it. :)
All that code for such a small thing looks like pure junk to me so I
would copy/paste and change the important parts to give it a try at
first, then rewrite it later. I saw MS' example after already writing
most of my (non-production) code from scratch.
> HDD space is measured in base 10, meaning kilo is 1000 instead of 1024.
> It can cause quite some confusion for people when it's calculated
> differently here and there. That's why I say KiB (kibibytes - kilo
> binary bytes) like others also are doing, but I am not sure if it is a
> standard (it was not at the time I learned about it, I think). So if the
Using "KiB" only resolves half the ambiguity. People still have to use
context and guesswork to understand what someone means when they say
"KB" (unless they've seen the same person use "KiB" somewhere else).
That's why I can't get behind the "KiB" movement. It's advocated by
people who want to reclaim the SI suffixes at any cost; not by people
who want to actually resolve the ambiguity. In fact, the "KiB"
movement is *adding* ambiguity not taking it away. (Until recently, if
you saw "KB" in a user interface, and it wasn't measuring raw disk
size or network throughput, you could be pretty sure it was a multiple
of 1024. Now you can be less sure what it means in any context. The
contexts where "KiB" is actually used were almost all unambiguously
multiples of 1024 when "KB" was used in the past, so that hasn't
helped much either. Not that it wasn't an unfortunate problem
originally, but it's been made worse, not better.)
If the "KiB" movement had also advocated new suffixes for the
multiples of 1000 in computing contexts, with the aim of never using
the ambiguous SI-style suffixes at all when discussing byte sizes,
then I might have joined them.
We're going a bit away from the original topic now but of course, that
doesn't change unless everyone does the same. I wouldn't say it's "the
solution" because I feel it's more like taking a shortcut and avoiding
the real problem. While someone isn't making a final decision on a
standard, we will however know immediately what is meant when someone
says KiB (while the ambiguity is still indifferent with kB).
At least while I was in school, I learned that kilo == 1000. When I
started using computers, nobody told me when kilo == 1000 and when kilo
== 1024. I also wondered why I had "less" total storage capacity than
advertised.
Even while I studied electronics in collage, I had to teach my own
teacher that HDD manufacturers measures kilo as 1000 and not 1024 (and
that's why the number on the label is different from what you see in
Windows). So it's not easy. :(
I just noticed that I said this, but I meant that's what HDD
manufacturer do.
In the case of HDD manufacturers measuring memory in a decimal form is pure
economics that has nothing to do with electronics -- it is much more easy to
sell a 1.5 TB hard drive versus 1.36 TB one. And for the general public it
doesn't make any sense to argue about the difference between GB or GiB
either (I'm sure 90% of the population never even heard of the GiB
notation). It matters only when the most inquisitive ones look up a drive's
specs in My Computer and call up a customer service... but that is a
diffeent issue.
Guys, I'm going to drop the original problem, i.e. the difference between
reported 3.96GB and the actual 4.00 GB. I will simply round it up if the
difference is less than 0.05. That seems what MS is doing in the latest OS's
anyway.
Thanks everyone who contributed, and especially Jackie.
I wasn't really implying anything, but we had computer classes as well
but they had nothing to teach me -- more the opposite. Just the fact
that I had to teach my own teacher tells a bit how confusing this can be. :)
> Guys, I'm going to drop the original problem, i.e. the difference between
> reported 3.96GB and the actual 4.00 GB. I will simply round it up if the
> difference is less than 0.05. That seems what MS is doing in the latest OS's
> anyway.
Okay. I am not sure I could sleep without knowing I did it perfectly,
though. Haha. If you open the Resource Monitor, and go to the Memory
tab, you have "Hardware reserved" there. Does it add up if you use that
value? If not, I really have no idea what they are doing. It's a pretty
wild guess I am making that maybe it has something to do with it.
> Thanks everyone who contributed, and especially Jackie.
Thank you and you're welcome. :)
> Using "KiB" only resolves half the ambiguity. People still have to use
> context and guesswork to understand what someone means when they say
> "KB" (unless they've seen the same person use "KiB" somewhere else).
Leo,
I agree with you but really the solution is for the disk manufacturers to
actually be honest about the true size of a drive. Resorting to KiB is
helping to cover up dishonest marketing and should not be supported at all.
An older method (that I had thought was accepted
by now) is to use "kB" for 1024 and "kb" for 1000
bytes. Similarly, MB = 1024^2, GB = 1024^3, etc.
Same SI prefix letters, but different
interpretation of size based on 'B' or 'b' case.
But even aside from the logical inconsistency, you
were never quite sure what was really intended
when you saw any given value floating around in a
spec.
Some manufacturers used to write out the full size
like "536,870,912 bytes", but with today's drives
having so much higher capacity, it would be pretty
cumbersome.
Best regards,
Bob Masta
DAQARTA v5.10
Data AcQuisition And Real-Time Analysis
www.daqarta.com
Scope, Spectrum, Spectrogram, Sound Level Meter
Frequency Counter, FREE Signal Generator
Pitch Track, Pitch-to-MIDI
DaqMusic - FREE MUSIC, Forever!
(Some assembly required)
Science (and fun!) with your sound card!
> In the case of HDD manufacturers measuring memory in a decimal form is pure
> economics that has nothing to do with electronics -- it is much more easy to
> sell a 1.5 TB hard drive versus 1.36 TB one. And for the general public it
> doesn't make any sense to argue about the difference between GB or GiB
> either (I'm sure 90% of the population never even heard of the GiB
> notation). It matters only when the most inquisitive ones look up a drive's
> specs in My Computer and call up a customer service... but that is a
> diffeent issue.
It's a "race to the bottom" effect. If your competitor is selling "1.5
TB" drives, you don't want to be selling "1.36 TB" drives for the same
price. The same thing happened with UPSes being rated in VA instead of
watts and their run time being quoted at 50% load.
DS
> An older method (that I had thought was accepted
> by now) is to use "kB" for 1024 and "kb" for 1000
> bytes.
At least in some contexts, lowercase 'b' means bits and uppercase 'B'
bytes.
It's like the people who thought up the size names and suffixes made
them confusing on purpose. :)
That's the same issue as cable companies being able to do whatever they want
selling us bundled packages, or cell phone companies jacking up cell phone
bills every month practically without any oversight.
Sorry for delay. I can run this on Win7 only. If I go to resource monitor,
it says:
Total 8151 MB
Installed 8192 MB
and then up above Hardware Reserved 41 MB
It beats me where it takes those numbers from....
That looks very not right because it is under "Physical Memory", right?
My only guess would be it also includes virtual memory. I don't have it
enabled right now so I can't check it out at the moment. On my system,
however, it says:
Total: 4094 MB
Installed: 4096 MB
Hardware Reserved: 2 MB
That number (4094 MB) is somehow the same as the number I see when
getting the total amount of visible memory with WMI. I don't know if it
has anything to do with it.
It's getting rather strange to me now. Haha.
--
Regards,
Jackie
IDK, here's my current reading. And yes, this Physical Memory section:
Available: 6536 MB
Cached: 2498 MB
Total: 8151 MB
Installed: 8192 MB
GlobalMemoryStatusEx() returns 7.96GB
Why would it report 7GB as total is beyond me? My only guess is that the ATI
card has 1 GB of memory. Do they make it so that GPU uses system RAM as
well?
On the sidenote, I got a response from Microsoft about this issue. I posted
a comment on the MSDN page and they responded that I should use
GetPhysicallyInstalledSystemMemory(). I tried it and it reports 8GB
installed (correctly), but I cannot try it on a XP system.
Aah. I thought this was on the machine that had 4 GB memory installed.
That's why I thought it was strange.
But then.. If you try this...
Installed = 8192 MB
Total = 8151 MB
Does Hardware Reserved == (Installed - Total)? (8192 - 8151) = 41 MB
I think this would make even more sense after reading on
http://msdn.microsoft.com/en-us/library/cc300158(VS.85).aspx
"The amount of memory available to the operating system can be less than
the amount of memory physically installed in the computer because the
BIOS and some drivers may reserve memory as I/O regions for
memory-mapped devices, making the memory unavailable to the operating
system and applications."
This seems to be what I came to think of before.
I think that I would just go with letting the user know exactly how much
is really installed, how much is available to the system (and not round
it up), and show how much is reserved.
--
Regards,
Jackie
BTW. Do you have any experience dealing with CPU usage? I posted a separate
question, "Correct code to get CPU usage"